Snap for 6533464 from 68f9f84932f0f0dbbbb9dbf0b0a3c25bce75ef45 to sdk-release

Change-Id: I04283d9a07dad943f22fc246b1c4fa46e1feb1bf
diff --git a/Android.bp b/Android.bp
index 373c402..fd46e81 100644
--- a/Android.bp
+++ b/Android.bp
@@ -221,6 +221,18 @@
     test_suites: ["device-tests"],
 }
 
+// Header-only library used for atrace in platform NDK builds
+cc_library_headers {
+    name: "libandroid_aidltrace",
+    host_supported: true,
+    vendor_available: true,
+    export_include_dirs: ["trace"],
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+}
+
 // Could consider simplifying this test by removing this.
 cc_test {
     name: "aidl_test_sentinel_searcher",
@@ -244,6 +256,7 @@
     name: "libaidl-integration-test",
     defaults: ["aidl_test_defaults"],
     aidl: {
+        generate_traces: true,
         export_aidl_headers: true,
         local_include_dirs: ["tests"],
         include_dirs: ["frameworks/native/aidl/binder"],
@@ -258,15 +271,14 @@
     name: "aidl_test_service",
     gtest: false,
     defaults: ["aidl_test_defaults"],
-    static_libs: ["libaidl-integration-test"],
+    static_libs: ["libaidl-integration-test", "libcutils"],
     srcs: ["tests/aidl_test_service.cpp"],
 }
 
 cc_test {
     name: "aidl_test_client",
-    gtest: false,
     defaults: ["aidl_test_defaults"],
-    static_libs: ["libaidl-integration-test"],
+    static_libs: ["libaidl-integration-test", "libcutils"],
     srcs: [
         "tests/aidl_test_client.cpp",
         "tests/aidl_test_client_file_descriptors.cpp",
@@ -310,6 +322,7 @@
             "system/tools/aidl/tests/",
             "frameworks/native/aidl/binder",
         ],
+        generate_traces: true,
     },
     test_suites: ["device-tests"],
 }
@@ -333,5 +346,8 @@
         ndk: {
             gen_log: true,
         },
+        java: {
+            platform_apis: true,
+        }
     },
 }
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..02409cb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+Documentation for this project is currently maintained here:
+
+https://source.android.com/devices/architecture/aidl/overview
diff --git a/aidl.cpp b/aidl.cpp
index 47e806c..0c10cdb 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -481,7 +481,7 @@
     }
     string import_path = import_resolver.FindImportFile(import);
     if (import_path.empty()) {
-      if (typenames->ResolveTypename(import).second) {
+      if (typenames->ResolveTypename(import).is_resolved) {
         // 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
@@ -574,7 +574,7 @@
     CHECK(defined_type != nullptr);
 
     // Language specific validation
-    if (!defined_type->LanguageSpecificCheckValid(options.TargetLanguage())) {
+    if (!defined_type->LanguageSpecificCheckValid(*typenames, options.TargetLanguage())) {
       return AidlError::BAD_TYPE;
     }
 
@@ -703,6 +703,35 @@
       AIDL_ERROR(type) << type.GetCanonicalName()
                        << " does not have VINTF level stability, but this interface requires it.";
     }
+
+    // Ensure that untyped List/Map is not used in stable AIDL.
+    if (options.IsStructured()) {
+      const AidlInterface* iface = type.AsInterface();
+      const AidlStructuredParcelable* parcelable = type.AsStructuredParcelable();
+
+      auto check = [&err](const AidlTypeSpecifier& type, const AidlNode* node) {
+        if (!type.IsGeneric() && (type.GetName() == "List" || type.GetName() == "Map")) {
+          err = AidlError::BAD_TYPE;
+          AIDL_ERROR(node)
+              << "Encountered an untyped List or Map. The use of untyped List/Map is prohibited "
+              << "because it is not guaranteed that the objects in the list are recognizable in "
+              << "the receiving side. Consider switching to an array or a generic List/Map.";
+        }
+      };
+
+      if (iface != nullptr) {
+        for (const auto& method : iface->GetMethods()) {
+          check(method->GetType(), method.get());
+          for (const auto& arg : method->GetArguments()) {
+            check(arg->GetType(), method.get());
+          }
+        }
+      } else if (parcelable != nullptr) {
+        for (const auto& field : parcelable->GetFields()) {
+          check(field->GetType(), field.get());
+        }
+      }
+    }
   });
 
   if (err != AidlError::OK) {
diff --git a/aidl_checkapi.cpp b/aidl_checkapi.cpp
index 2ae2247..72577ca 100644
--- a/aidl_checkapi.cpp
+++ b/aidl_checkapi.cpp
@@ -34,12 +34,35 @@
 using std::string;
 using std::vector;
 
+static set<AidlAnnotation> get_strict_annotations(const AidlAnnotatable& node) {
+  // This must be symmetrical (if you can add something, you must be able to
+  // remove it). The reason is that we have no way of knowing which interface a
+  // server serves and which interface a client serves (e.g. a callback
+  // interface). Note that this is being overly lenient. It makes sense for
+  // newer code to start accepting nullable things. However, here, we don't know
+  // if the client of an interface or the server of an interface is newer.
+  //
+  // Here are two examples to demonstrate this:
+  // - a new implementation might change so that it no longer returns null
+  // values (remove @nullable)
+  // - a new implementation might start accepting null values (add @nullable)
+  static const set<AidlAnnotation::Type> kIgnoreAnnotations{
+      AidlAnnotation::Type::NULLABLE,
+  };
+  set<AidlAnnotation> annotations;
+  for (const AidlAnnotation& annotation : node.GetAnnotations()) {
+    if (kIgnoreAnnotations.find(annotation.GetType()) == kIgnoreAnnotations.end()) {
+      annotations.insert(annotation);
+    }
+  }
+  return annotations;
+}
+
 static bool have_compatible_annotations(const AidlAnnotatable& older,
                                         const AidlAnnotatable& newer) {
-  set<AidlAnnotation> olderAnnotations(older.GetAnnotations().begin(),
-                                       older.GetAnnotations().end());
-  set<AidlAnnotation> newerAnnotations(newer.GetAnnotations().begin(),
-                                       newer.GetAnnotations().end());
+  set<AidlAnnotation> olderAnnotations = get_strict_annotations(older);
+  set<AidlAnnotation> newerAnnotations = get_strict_annotations(newer);
+
   if (olderAnnotations != newerAnnotations) {
     const string from = older.ToString().empty() ? "(empty)" : older.ToString();
     const string to = newer.ToString().empty() ? "(empty)" : newer.ToString();
@@ -142,6 +165,19 @@
   return compatible;
 }
 
+// returns whether the given type when defaulted will be accepted by
+// unmarshalling code
+static bool has_usable_nil_type(const AidlTypeSpecifier& specifier) {
+  // TODO(b/155238508): fix for primitives
+
+  // This technically only applies in C++, but even if both the client and the
+  // server of an interface are in Java at a particular point in time, where
+  // null is currently always acceptable, we want to make sure that versions
+  // of this service can work in native and future backends without a problem.
+  // Also, in that case, adding nullable does not hurt.
+  return specifier.IsNullable();
+}
+
 static bool are_compatible_parcelables(const AidlStructuredParcelable& older,
                                        const AidlStructuredParcelable& newer) {
   const auto& old_fields = older.GetFields();
@@ -159,19 +195,62 @@
     const auto& new_field = new_fields.at(i);
     compatible &= are_compatible_types(old_field->GetType(), new_field->GetType());
 
-    // Note: unlike method argument names, field name change is an incompatible
-    // change, otherwise, we can't detect
-    // parcelable Point {int x; int y;} -> parcelable Point {int y; int x;}
-    if (old_field->GetName() != new_field->GetName()) {
-      AIDL_ERROR(newer) << "Renamed field: " << old_field->GetName() << " to "
-                        << new_field->GetName() << ".";
-      compatible = false;
-    }
-
     const string old_value = old_field->ValueString(AidlConstantValueDecorator);
     const string new_value = new_field->ValueString(AidlConstantValueDecorator);
     if (old_value != new_value) {
-      AIDL_ERROR(newer) << "Changed default value: " << old_value << " to " << new_value << ".";
+      AIDL_ERROR(new_field) << "Changed default value: " << old_value << " to " << new_value << ".";
+      compatible = false;
+    }
+  }
+
+  // Reordering of fields is an incompatible change.
+  for (size_t i = 0; i < new_fields.size(); i++) {
+    const auto& new_field = new_fields.at(i);
+    auto found = std::find_if(old_fields.begin(), old_fields.end(), [&new_field](const auto& f) {
+      return new_field->GetName() == f->GetName();
+    });
+    if (found != old_fields.end()) {
+      size_t old_index = std::distance(old_fields.begin(), found);
+      if (old_index != i) {
+        AIDL_ERROR(new_field) << "Reordered " << new_field->GetName() << " from " << old_index
+                              << " to " << i << ".";
+        compatible = false;
+      }
+    }
+  }
+
+  for (size_t i = old_fields.size(); i < new_fields.size(); i++) {
+    const auto& new_field = new_fields.at(i);
+    if (!new_field->GetDefaultValue() && !has_usable_nil_type(new_field->GetType())) {
+      // Old API versions may suffer from the issue presented here. There is
+      // only a finite number in Android, which we must allow indefinitely.
+      struct HistoricalException {
+        std::string canonical;
+        std::string field;
+      };
+      static std::vector<HistoricalException> exceptions = {
+          {"android.net.DhcpResultsParcelable", "serverHostName"},
+          {"android.net.ProvisioningConfigurationParcelable", "enablePreconnection"},
+          {"android.net.ResolverParamsParcel", "resolverOptions"},
+      };
+      bool excepted = false;
+      for (const HistoricalException& exception : exceptions) {
+        if (older.GetCanonicalName() == exception.canonical &&
+            new_field->GetName() == exception.field) {
+          excepted = true;
+          break;
+        }
+      }
+      if (excepted) continue;
+
+      AIDL_ERROR(new_field)
+          << "Field '" << new_field->GetName()
+          << "' does not have a useful default in some backends. Please either provide a default "
+             "value for this field or mark the field as @nullable. This value or a null value will "
+             "be used automatically when an old version of this parcelable is sent to a process "
+             "which understands a new version of this parcelable. In order to make sure your code "
+             "continues to be backwards compatible, make sure the default or null value does not "
+             "cause a semantic change to this parcelable.";
       compatible = false;
     }
   }
diff --git a/aidl_language.cpp b/aidl_language.cpp
index e08142a..dd726d6 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -200,7 +200,7 @@
     if (parameter_mapping_it == schema_.supported_parameters.end()) {
       std::ostringstream stream;
       stream << "Parameter " << param_name << " not supported ";
-      stream << "for annotation " << GetName() << ".";
+      stream << "for annotation " << GetName() << ". ";
       stream << "It must be one of:";
       for (const auto& kv : schema_.supported_parameters) {
         stream << " " << kv.first;
@@ -226,13 +226,23 @@
   for (const auto& name_and_param : parameters_) {
     const std::string& param_name = name_and_param.first;
     const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
+    if (schema_.supported_parameters.find(param_name) == schema_.supported_parameters.end()) {
+      std::ostringstream stream;
+      stream << "Parameter " << param_name << " not supported ";
+      stream << "for annotation " << GetName() << ". ";
+      stream << "It must be one of:";
+      for (const auto& kv : schema_.supported_parameters) {
+        stream << " " << kv.first;
+      }
+      AIDL_ERROR(this) << stream.str();
+      continue;
+    }
     AidlTypeSpecifier type{AIDL_LOCATION_HERE, schema_.supported_parameters.at(param_name), false,
                            nullptr, ""};
     if (!param->CheckValid()) {
       AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
                        << GetName() << ".";
-      raw_params.clear();
-      return raw_params;
+      continue;
     }
 
     raw_params.emplace(param_name, param->ValueString(type, decorator));
@@ -396,12 +406,12 @@
 
 bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
   CHECK(!IsResolved());
-  pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
-  if (result.second) {
-    fully_qualified_name_ = result.first;
+  AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
+  if (result.is_resolved) {
+    fully_qualified_name_ = result.canonical_name;
     split_name_ = Split(fully_qualified_name_, ".");
   }
-  return result.second;
+  return result.is_resolved;
 }
 
 std::set<AidlAnnotation::Type> AidlTypeSpecifier::GetSupportedAnnotations() const {
@@ -822,7 +832,24 @@
 }
 
 // TODO: we should treat every backend all the same in future.
-bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
+bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
+                                                   Options::Language lang) const {
+  if (lang == Options::Language::NDK && IsArray() && GetName() == "IBinder") {
+    AIDL_ERROR(this) << "The NDK backend does not support array of IBinder";
+    return false;
+  }
+  if (lang == Options::Language::NDK && IsArray() && IsNullable()) {
+    if (GetName() == "ParcelFileDescriptor") {
+      AIDL_ERROR(this) << "The NDK backend does not support nullable array of ParcelFileDescriptor";
+      return false;
+    }
+
+    const auto defined_type = typenames.TryGetDefinedType(GetName());
+    if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
+      AIDL_ERROR(this) << "The NDK backend does not support nullable array of parcelable";
+      return false;
+    }
+  }
   if (lang != Options::Language::JAVA) {
     if (this->GetName() == "List" && !this->IsGeneric()) {
       AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
@@ -881,7 +908,8 @@
 }
 
 // TODO: we should treat every backend all the same in future.
-bool AidlParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
+bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
+                                                Options::Language lang) const {
   if (lang != Options::Language::JAVA) {
     const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
     if (unstructured_parcelable != nullptr) {
@@ -896,12 +924,13 @@
 }
 
 // TODO: we should treat every backend all the same in future.
-bool AidlStructuredParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
-  if (!AidlParcelable::LanguageSpecificCheckValid(lang)) {
+bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
+                                                          Options::Language lang) const {
+  if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
     return false;
   }
   for (const auto& v : this->GetFields()) {
-    if (!v->GetType().LanguageSpecificCheckValid(lang)) {
+    if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
       return false;
     }
   }
@@ -997,13 +1026,14 @@
 }
 
 // TODO: we should treat every backend all the same in future.
-bool AidlInterface::LanguageSpecificCheckValid(Options::Language lang) const {
+bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
+                                               Options::Language lang) const {
   for (const auto& m : this->GetMethods()) {
-    if (!m->GetType().LanguageSpecificCheckValid(lang)) {
+    if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
       return false;
     }
     for (const auto& arg : m->GetArguments()) {
-      if (!arg->GetType().LanguageSpecificCheckValid(lang)) {
+      if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
         return false;
       }
     }
diff --git a/aidl_language.h b/aidl_language.h
index 44c8078..2d388e8 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -356,7 +356,7 @@
 
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(Options::Language lang) const;
+  bool LanguageSpecificCheckValid(const AidlTypenames& typenames, Options::Language lang) const;
   const AidlNode& AsAidlNode() const override { return *this; }
 
  private:
@@ -706,7 +706,8 @@
   virtual const AidlInterface* AsInterface() const { return nullptr; }
   virtual const AidlParameterizable<std::string>* AsParameterizable() const { return nullptr; }
   bool CheckValid(const AidlTypenames& typenames) const override;
-  virtual bool LanguageSpecificCheckValid(Options::Language lang) const = 0;
+  virtual bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
+                                          Options::Language lang) const = 0;
   AidlStructuredParcelable* AsStructuredParcelable() {
     return const_cast<AidlStructuredParcelable*>(
         const_cast<const AidlDefinedType*>(this)->AsStructuredParcelable());
@@ -761,7 +762,8 @@
 
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(Options::Language lang) const override;
+  bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
+                                  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; }
@@ -793,7 +795,8 @@
 
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(Options::Language lang) const override;
+  bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
+                                  Options::Language lang) const override;
 
  private:
   const std::vector<std::unique_ptr<AidlVariableDeclaration>> variables_;
@@ -840,7 +843,10 @@
   bool Autofill();
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(Options::Language) const override { return true; }
+  bool LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
+                                  Options::Language) const override {
+    return true;
+  }
   std::string GetPreprocessDeclarationName() const override { return "enum"; }
   void Dump(CodeWriter* writer) const override;
 
@@ -875,7 +881,8 @@
 
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(Options::Language lang) const override;
+  bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
+                                  Options::Language lang) const override;
 
  private:
   std::vector<std::unique_ptr<AidlMethod>> methods_;
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index 3a1fda9..9784625 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -116,7 +116,7 @@
 
 %token '(' ')' ',' '=' '[' ']' '.' '{' '}' ';'
 %token UNKNOWN "unrecognized character"
-%token CPP_HEADER "cpp_header"
+%token CPP_HEADER "cpp_header (which can also be used as an identifier)"
 %token IMPORT "import"
 %token IN "in"
 %token INOUT "inout"
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index 8b4bc1c..e5ac195 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -364,15 +364,18 @@
 
   if (aidl.IsArray()) {
     if (aidl.IsNullable()) {
-      AIDL_FATAL_IF(info.nullable_array == nullptr, aidl) << "Unsupported type in NDK Backend.";
+      AIDL_FATAL_IF(info.nullable_array == nullptr, aidl)
+          << "Unsupported type in NDK Backend: " << aidl.ToString();
       return *info.nullable_array;
     }
-    AIDL_FATAL_IF(info.array == nullptr, aidl) << "Unsupported type in NDK Backend.";
+    AIDL_FATAL_IF(info.array == nullptr, aidl)
+        << "Unsupported type in NDK Backend: " << aidl.ToString();
     return *info.array;
   }
 
   if (aidl.IsNullable()) {
-    AIDL_FATAL_IF(info.nullable == nullptr, aidl) << "Unsupported type in NDK Backend.";
+    AIDL_FATAL_IF(info.nullable == nullptr, aidl)
+        << "Unsupported type in NDK Backend: " << aidl.ToString();
     return *info.nullable;
   }
 
diff --git a/aidl_typenames.cpp b/aidl_typenames.cpp
index ad89c1c..349ccbe 100644
--- a/aidl_typenames.cpp
+++ b/aidl_typenames.cpp
@@ -64,21 +64,30 @@
 // in Java and C++. Using these names will eventually cause compilation error,
 // so checking this here is not a must have, but early detection of errors
 // is always better.
-static const set<string> kInvalidNames = {
+static const set<string> kCppOrJavaReservedWord = {
     "break",  "case",   "catch", "char",     "class",  "continue", "default",
     "do",     "double", "else",  "enum",     "false",  "float",    "for",
     "goto",   "if",     "int",   "long",     "new",    "private",  "protected",
     "public", "return", "short", "static",   "switch", "this",     "throw",
     "true",   "try",    "void",  "volatile", "while"};
 
-static bool IsValidName(const string& name) {
-  vector<string> pieces = Split(name, ".");
-  for (const auto& piece : pieces) {
-    if (kInvalidNames.find(piece) != kInvalidNames.end()) {
-      return false;
+static bool HasValidNameComponents(const AidlDefinedType& defined) {
+  bool success = true;
+  vector<string> pieces = Split(defined.GetCanonicalName(), ".");
+  for (const string& piece : pieces) {
+    if (kCppOrJavaReservedWord.find(piece) != kCppOrJavaReservedWord.end()) {
+      AIDL_ERROR(defined) << defined.GetCanonicalName() << " is an invalid name because '" << piece
+                          << "' is a Java or C++ identifier.";
+      success = false;
+    }
+    // not checking kJavaLikeTypeToAidl, since that wouldn't make sense here
+    if (kBuiltinTypes.find(piece) != kBuiltinTypes.end()) {
+      AIDL_ERROR(defined) << defined.GetCanonicalName() << " is an invalid name because '" << piece
+                          << "' is a built-in AIDL type.";
+      success = false;
     }
   }
-  return true;
+  return success;
 }
 
 bool AidlTypenames::IsIgnorableImport(const string& import) const {
@@ -99,7 +108,7 @@
   if (defined_types_.find(name) != defined_types_.end()) {
     return false;
   }
-  if (!IsValidName(type->GetPackage()) || !IsValidName(type->GetName())) {
+  if (!HasValidNameComponents(*type)) {
     return false;
   }
   defined_types_.emplace(name, std::move(type));
@@ -111,7 +120,7 @@
   if (preprocessed_types_.find(name) != preprocessed_types_.end()) {
     return false;
   }
-  if (!IsValidName(type->GetPackage()) || !IsValidName(type->GetName())) {
+  if (!HasValidNameComponents(*type)) {
     return false;
   }
   preprocessed_types_.insert(make_pair(name, std::move(type)));
@@ -161,19 +170,19 @@
   return DefinedImplResult(nullptr, false);
 }
 
-pair<string, bool> AidlTypenames::ResolveTypename(const string& type_name) const {
+AidlTypenames::ResolvedTypename AidlTypenames::ResolveTypename(const string& type_name) const {
   if (IsBuiltinTypename(type_name)) {
     auto found = kJavaLikeTypeToAidlType.find(type_name);
     if (found != kJavaLikeTypeToAidlType.end()) {
-      return make_pair(found->second, true);
+      return {found->second, true};
     }
-    return make_pair(type_name, true);
+    return {type_name, true};
   }
   const AidlDefinedType* defined_type = TryGetDefinedType(type_name);
   if (defined_type != nullptr) {
-    return make_pair(defined_type->GetCanonicalName(), true);
+    return {defined_type->GetCanonicalName(), true};
   } else {
-    return make_pair(type_name, false);
+    return {type_name, false};
   }
 }
 
diff --git a/aidl_typenames.h b/aidl_typenames.h
index 78b996f..3b01ada 100644
--- a/aidl_typenames.h
+++ b/aidl_typenames.h
@@ -58,7 +58,12 @@
   static bool IsBuiltinTypename(const string& type_name);
   static bool IsPrimitiveTypename(const string& type_name);
   const AidlDefinedType* TryGetDefinedType(const string& type_name) const;
-  pair<string, bool> ResolveTypename(const string& type_name) const;
+
+  struct ResolvedTypename {
+    std::string canonical_name;
+    bool is_resolved;
+  };
+  ResolvedTypename ResolveTypename(const string& type_name) const;
   bool CanBeOutParameter(const AidlTypeSpecifier& type) const;
   bool IsIgnorableImport(const string& import) const;
   // Returns the AidlEnumDeclaration of the given type, or nullptr if the type
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 99f8cdc..6266ee3 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include <android-base/stringprintf.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include "aidl.h"
@@ -451,6 +452,24 @@
   EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
 }
 
+TEST_P(AidlTest, AnnotationsInMultiplePlaces) {
+  const string oneway_method =
+      "package a; interface IFoo { @UnsupportedAppUsage oneway @Hide void f(int a); }";
+  const AidlDefinedType* defined = Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage());
+  ASSERT_NE(nullptr, defined);
+  const AidlInterface* iface = defined->AsInterface();
+  ASSERT_NE(nullptr, iface);
+
+  const auto& methods = iface->GetMethods();
+  ASSERT_EQ(1u, methods.size());
+  const auto& method = methods[0];
+  const AidlTypeSpecifier& ret_type = method->GetType();
+
+  // TODO(b/151102494): these annotations should be on the method
+  ASSERT_NE(nullptr, ret_type.UnsupportedAppUsage());
+  ASSERT_TRUE(ret_type.IsHide());
+}
+
 TEST_P(AidlTest, WritesComments) {
   string foo_interface =
       "package a; /* foo */ interface IFoo {"
@@ -471,20 +490,20 @@
 TEST_F(AidlTest, ParsesPreprocessedFile) {
   string simple_content = "parcelable a.Foo;\ninterface b.IBar;";
   io_delegate_.SetFileContents("path", simple_content);
-  EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").second);
+  EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").is_resolved);
   EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &typenames_));
-  EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").second);
-  EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").second);
+  EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").is_resolved);
+  EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").is_resolved);
 }
 
 TEST_F(AidlTest, ParsesPreprocessedFileWithWhitespace) {
   string simple_content = "parcelable    a.Foo;\n  interface b.IBar  ;\t";
   io_delegate_.SetFileContents("path", simple_content);
 
-  EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").second);
+  EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").is_resolved);
   EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &typenames_));
-  EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").second);
-  EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").second);
+  EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").is_resolved);
+  EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").is_resolved);
 }
 
 TEST_P(AidlTest, PreferImportToPreprocessed) {
@@ -498,8 +517,8 @@
   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);
+  EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
+  EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
   // But if we request just "IBar" we should get our imported one.
   AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, "");
   ambiguous_type.Resolve(typenames_);
@@ -520,8 +539,8 @@
   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);
+  EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
+  EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
   // But if we request just "IBar" we should get our imported one.
   AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, "");
   ambiguous_type.Resolve(typenames_);
@@ -761,8 +780,7 @@
   auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
   EXPECT_NE(nullptr, parse_result);
 
-  auto pair = typenames_.ResolveTypename("p.Outer.Inner");
-  EXPECT_TRUE(pair.second);
+  EXPECT_TRUE(typenames_.ResolveTypename("p.Outer.Inner").is_resolved);
   // C++ uses "::" instead of "." to refer to a inner class.
   AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", false, nullptr, "");
   EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
@@ -777,8 +795,7 @@
   const string input = "package p; import p.Bar; interface IFoo { }";
   auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
   EXPECT_NE(nullptr, parse_result);
-  auto pair = typenames_.ResolveTypename("p.Bar");
-  EXPECT_TRUE(pair.second);
+  EXPECT_TRUE(typenames_.ResolveTypename("p.Bar").is_resolved);
   AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", false, nullptr, "");
   native_type.Resolve(typenames_);
 
@@ -911,6 +928,37 @@
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
+TEST_P(AidlTest, RejectsPrimitiveListInStableAidl) {
+  AidlError error;
+  string expected_stderr =
+      "ERROR: a/IFoo.aidl:2.7-11: "
+      "Encountered an untyped List or Map. The use of untyped List/Map is "
+      "prohibited because it is not guaranteed that the objects in the list are recognizable in "
+      "the receiving side. Consider switching to an array or a generic List/Map.\n";
+  if (GetLanguage() != Options::Language::JAVA) {
+    expected_stderr =
+        "ERROR: a/IFoo.aidl:2.1-7: "
+        "Currently, only the Java backend supports non-generic List.\n";
+  }
+
+  const string primitive_interface =
+      "package a; interface IFoo {\n"
+      "  List foo(); }";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_interface, typenames_, GetLanguage(), &error,
+                           {"--structured"}));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  typenames_.Reset();
+
+  string primitive_parcelable =
+      "package a; parcelable IFoo {\n"
+      "  List foo;}";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_parcelable, typenames_, GetLanguage(), &error,
+                           {"--structured"}));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+}
+
 TEST_F(AidlTest, ApiDump) {
   io_delegate_.SetFileContents(
       "foo/bar/IFoo.aidl",
@@ -1323,6 +1371,7 @@
                                "interface IFoo {"
                                "  void foo(int a);"
                                "  void bar();"
+                               "  void baz(in List<IFoo> arg);"
                                "}");
   EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
 }
@@ -1337,7 +1386,8 @@
                                "package p;"
                                "parcelable Data {"
                                "  int foo;"
-                               "  int bar;"
+                               "  int bar = 0;"
+                               "  @nullable List<Data> list;"
                                "}");
   EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
 }
@@ -1478,6 +1528,52 @@
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
+TEST_F(AidlTestIncompatibleChanges, UntypedListInInterface) {
+  const string expected_stderr =
+      "ERROR: new/p/IFoo.aidl:1.61-65: "
+      "Encountered an untyped List or Map. The use of untyped List/Map is "
+      "prohibited because it is not guaranteed that the objects in the list are recognizable in "
+      "the receiving side. Consider switching to an array or a generic List/Map.\n"
+      "ERROR: new/p/IFoo.aidl: Failed to read.\n";
+  io_delegate_.SetFileContents("old/p/IFoo.aidl",
+                               "package p;"
+                               "interface IFoo {"
+                               "  void foo(in String[] str);"
+                               "}");
+  io_delegate_.SetFileContents("new/p/IFoo.aidl",
+                               "package p;"
+                               "interface IFoo {"
+                               "  void foo(in String[] str);"
+                               "  void bar(in List arg);"
+                               "}");
+  CaptureStderr();
+  EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+}
+
+TEST_F(AidlTestCompatibleChanges, UntypedListInParcelable) {
+  const string expected_stderr =
+      "ERROR: new/p/Data.aidl:1.54-59: "
+      "Encountered an untyped List or Map. The use of untyped List/Map is "
+      "prohibited because it is not guaranteed that the objects in the list are recognizable in "
+      "the receiving side. Consider switching to an array or a generic List/Map.\n"
+      "ERROR: new/p/Data.aidl: Failed to read.\n";
+  io_delegate_.SetFileContents("old/p/Data.aidl",
+                               "package p;"
+                               "parcelable Data {"
+                               "  int foo;"
+                               "}");
+  io_delegate_.SetFileContents("new/p/Data.aidl",
+                               "package p;"
+                               "parcelable Data {"
+                               "  int foo;"
+                               "  @nullable List list;"
+                               "}");
+  CaptureStderr();
+  EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+}
+
 TEST_F(AidlTestIncompatibleChanges, RemovedField) {
   const string expected_stderr =
       "ERROR: new/p/Data.aidl:1.21-26: Number of fields in p.Data is reduced from 2 to 1.\n";
@@ -1536,25 +1632,6 @@
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTestIncompatibleChanges, RenamedField) {
-  const string expected_stderr = "ERROR: new/p/Data.aidl:1.21-26: Renamed field: bar to bar2.\n";
-  io_delegate_.SetFileContents("old/p/Data.aidl",
-                               "package p;"
-                               "parcelable Data {"
-                               "  int foo;"
-                               "  int bar;"
-                               "}");
-  io_delegate_.SetFileContents("new/p/Data.aidl",
-                               "package p;"
-                               "parcelable Data {"
-                               "  int foo;"
-                               "  int bar2;"
-                               "}");
-  CaptureStderr();
-  EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-}
-
 TEST_F(AidlTestIncompatibleChanges, RenamedType) {
   const string expected_stderr = "ERROR: old/p/IFoo.aidl:1.11-20: Removed type: p.IFoo\n";
   io_delegate_.SetFileContents("old/p/IFoo.aidl",
@@ -1619,8 +1696,8 @@
 
 TEST_F(AidlTestIncompatibleChanges, ReorderedField) {
   const string expected_stderr =
-      "ERROR: new/p/Data.aidl:1.21-26: Renamed field: foo to bar.\n"
-      "ERROR: new/p/Data.aidl:1.21-26: Renamed field: bar to foo.\n";
+      "ERROR: new/p/Data.aidl:1.33-37: Reordered bar from 1 to 0.\n"
+      "ERROR: new/p/Data.aidl:1.43-47: Reordered foo from 0 to 1.\n";
   io_delegate_.SetFileContents("old/p/Data.aidl",
                                "package p;"
                                "parcelable Data {"
@@ -1708,7 +1785,7 @@
 }
 
 TEST_F(AidlTestIncompatibleChanges, ChangedDefaultValue) {
-  const string expected_stderr = "ERROR: new/p/D.aidl:1.22-24: Changed default value: 1 to 2.\n";
+  const string expected_stderr = "ERROR: new/p/D.aidl:1.30-32: Changed default value: 1 to 2.\n";
   io_delegate_.SetFileContents("old/p/D.aidl", "package p; parcelable D { int a = 1; }");
   io_delegate_.SetFileContents("new/p/D.aidl", "package p; parcelable D { int a = 2; }");
   CaptureStderr();
@@ -1885,6 +1962,26 @@
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
+TEST_F(AidlTest, UnusedImportDoesNotContributeInclude) {
+  io_delegate_.SetFileContents("a/b/IFoo.aidl",
+                               "package a.b;\n"
+                               "import a.b.IBar;\n"
+                               "import a.b.IQux;\n"
+                               "interface IFoo { IQux foo(); }\n");
+  io_delegate_.SetFileContents("a/b/IBar.aidl", "package a.b; interface IBar { void foo(); }");
+  io_delegate_.SetFileContents("a/b/IQux.aidl", "package a.b; interface IQux { void foo(); }");
+
+  Options options = Options::From("aidl --lang=ndk a/b/IFoo.aidl -I . -o out -h out/include");
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+
+  string output;
+  EXPECT_TRUE(io_delegate_.GetWrittenContents("out/include/aidl/a/b/IFoo.h", &output));
+  // IBar was imported but wasn't used. include is not expected.
+  EXPECT_THAT(output, Not(testing::HasSubstr("#include <aidl/a/b/IBar.h>")));
+  // IBar was imported and used. include is expected.
+  EXPECT_THAT(output, (testing::HasSubstr("#include <aidl/a/b/IQux.h>")));
+}
+
 class AidlOutputPathTest : public AidlTest {
  protected:
   void SetUp() override {
@@ -2003,5 +2100,26 @@
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
+TEST_P(AidlTest, UnsupportedBackingAnnotationParam) {
+  AidlError error;
+  const string expected_stderr =
+      "ERROR: p/TestEnum.aidl:2.1-51: Parameter foo not supported for annotation Backing. It must "
+      "be one of: type\n"
+      "ERROR: p/TestEnum.aidl:2.1-51: Parameter foo not supported for annotation Backing. It must "
+      "be one of: type\n";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("p/TestEnum.aidl",
+                           R"(package p;
+                              @Backing(foo="byte")
+                              enum TestEnum {
+                                FOO = 1,
+                                BAR,
+                              }
+                             )",
+                           typenames_, GetLanguage(), &error));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  EXPECT_EQ(AidlError::BAD_TYPE, error);
+}
+
 }  // namespace aidl
 }  // namespace android
diff --git a/build/Android.bp b/build/Android.bp
index d537196..57eccc7 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -105,6 +105,12 @@
     imports: [
         "test-piece-1",
     ],
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+    },
+    gen_trace: true,
     versions: ["1"],
 }
 
@@ -117,6 +123,12 @@
     imports: [
         "test-piece-2",
     ],
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+    },
+    gen_trace: true,
     versions: ["1"],
 }
 
@@ -129,6 +141,12 @@
     imports: [
         "test-piece-1",
     ],
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+    },
+    gen_trace: true,
     versions: ["1"],
 }
 
@@ -140,6 +158,12 @@
     imports: [
         "test-piece-2",
     ],
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+    },
+    gen_trace: true,
     versions: [
         "1",
         "2",
diff --git a/build/aidl_interface.go b/build/aidl_interface.go
index 2f49307..4fb9285 100644
--- a/build/aidl_interface.go
+++ b/build/aidl_interface.go
@@ -480,8 +480,7 @@
 
 		i, err := strconv.Atoi(latestVersion)
 		if err != nil {
-			ctx.PropertyErrorf("versions", "%q is not an integer", latestVersion)
-			return ""
+			panic(err)
 		}
 
 		return strconv.Itoa(i + 1)
@@ -920,22 +919,38 @@
 	}
 }
 
+func (i *aidlInterface) checkGenTrace(mctx android.LoadHookContext) {
+	if !proptools.Bool(i.properties.Gen_trace) {
+		return
+	}
+	if i.shouldGenerateJavaBackend() && !proptools.Bool(i.properties.Backend.Java.Platform_apis) {
+		mctx.PropertyErrorf("gen_trace", "must be false when Java backend is enabled and platform_apis is false")
+	}
+}
+
 func (i *aidlInterface) checkStability(mctx android.LoadHookContext) {
 	if i.properties.Stability == nil {
 		return
 	}
 
+	if proptools.Bool(i.properties.Unstable) {
+		mctx.PropertyErrorf("stability", "must be empty when \"unstable\" is true")
+	}
+
 	// 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 }"
 	isVintf := "vintf" == proptools.String(i.properties.Stability)
 	if !isVintf {
 		mctx.PropertyErrorf("stability", "must be empty or \"vintf\"")
 	}
-
-	// TODO(b/152655544): might need to change the condition
-	sdkIsFinal := mctx.Config().DefaultAppTargetSdkInt() != android.FutureApiLevel
-	if sdkIsFinal && !i.hasVersion() && isVintf && i.Owner() == "" {
-		mctx.PropertyErrorf("versions", "must be set(need to be frozen) when stability is \"vintf\" and PLATFORM_VERSION_CODENAME is REL.")
+}
+func (i *aidlInterface) checkVersions(mctx android.LoadHookContext) {
+	for _, ver := range i.properties.Versions {
+		_, err := strconv.Atoi(ver)
+		if err != nil {
+			mctx.PropertyErrorf("versions", "%q is not an integer", ver)
+			continue
+		}
 	}
 }
 
@@ -946,8 +961,7 @@
 		ver := i.latestVersion()
 		i, err := strconv.Atoi(ver)
 		if err != nil {
-			ctx.PropertyErrorf("versions", "%q is not an integer", ver)
-			return ""
+			panic(err)
 		}
 
 		return strconv.Itoa(i + 1)
@@ -1040,6 +1054,8 @@
 
 	i.gatherInterface(mctx)
 	i.checkStability(mctx)
+	i.checkVersions(mctx)
+	i.checkGenTrace(mctx)
 
 	if mctx.Failed() {
 		return
@@ -1121,6 +1137,10 @@
 			mctx.ModuleErrorf("unstable:true and stability:%q cannot happen at the same time", i.properties.Stability)
 		}
 	} else {
+		sdkIsFinal := mctx.Config().DefaultAppTargetSdkInt() != android.FutureApiLevel
+		if sdkIsFinal && !i.hasVersion() && i.Owner() == "" {
+			mctx.PropertyErrorf("versions", "must be set (need to be frozen) when \"unstable\" is false and PLATFORM_VERSION_CODENAME is REL.")
+		}
 		addApiModule(mctx, i)
 	}
 
@@ -1188,8 +1208,10 @@
 	})
 
 	importExportDependencies := wrap("", i.properties.Imports, "-"+lang)
+	var sharedLibDependency []string
 	var libJSONCppDependency []string
 	var staticLibDependency []string
+	var headerLibs []string
 	var sdkVersion *string
 	var minSdkVersion *string
 	var stl *string
@@ -1203,7 +1225,7 @@
 			libJSONCppDependency = []string{"libjsoncpp"}
 		}
 		if genTrace {
-			importExportDependencies = append(importExportDependencies, "libcutils")
+			sharedLibDependency = append(sharedLibDependency, "libcutils")
 		}
 		hostSupported = i.properties.Host_supported
 		minSdkVersion = i.properties.Backend.Cpp.Min_sdk_version
@@ -1212,6 +1234,9 @@
 		if genLog {
 			staticLibDependency = []string{"libjsoncpp_ndk"}
 		}
+		if genTrace {
+			sharedLibDependency = append(sharedLibDependency, "libandroid")
+		}
 		sdkVersion = proptools.StringPtr("current")
 		stl = proptools.StringPtr("c++_shared")
 		minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
@@ -1220,6 +1245,10 @@
 		if genLog {
 			libJSONCppDependency = []string{"libjsoncpp"}
 		}
+		if genTrace {
+			headerLibs = append(headerLibs, "libandroid_aidltrace")
+			sharedLibDependency = append(sharedLibDependency, "libcutils")
+		}
 		hostSupported = i.properties.Host_supported
 		addCflags = append(addCflags, "-DBINDER_STABILITY_SUPPORT")
 		minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
@@ -1250,7 +1279,8 @@
 		Static:                    staticLib{Whole_static_libs: libJSONCppDependency},
 		Shared:                    sharedLib{Shared_libs: libJSONCppDependency, Export_shared_lib_headers: libJSONCppDependency},
 		Static_libs:               staticLibDependency,
-		Shared_libs:               importExportDependencies,
+		Shared_libs:               append(importExportDependencies, sharedLibDependency...),
+		Header_libs:               headerLibs,
 		Export_shared_lib_headers: importExportDependencies,
 		Sdk_version:               sdkVersion,
 		Stl:                       stl,
@@ -1294,6 +1324,7 @@
 		Lang:      langJava,
 		BaseName:  i.ModuleBase.Name(),
 		Version:   version,
+		GenTrace:  proptools.Bool(i.properties.Gen_trace),
 		Unstable:  i.properties.Unstable,
 	})
 
diff --git a/build/aidl_test.go b/build/aidl_test.go
index 9732675..8d40040 100644
--- a/build/aidl_test.go
+++ b/build/aidl_test.go
@@ -22,6 +22,7 @@
 	"testing"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
 	"android/soong/cc"
@@ -63,6 +64,13 @@
 	}
 }
 
+func setReleaseEnv() testCustomizer {
+	return func(_ map[string][]byte, config android.Config) {
+		config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("REL")
+		config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(true)
+	}
+}
+
 func _testAidl(t *testing.T, bp string, customizers ...testCustomizer) (*android.TestContext, android.Config) {
 	t.Helper()
 
@@ -120,6 +128,11 @@
 
 	config := android.TestArchConfig(buildDir, nil, bp, fs)
 
+	// To keep tests stable, fix Platform_sdk_codename and Platform_sdk_final
+	// Use setReleaseEnv() to test release version
+	config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
+	config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
+
 	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
@@ -143,7 +156,9 @@
 
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
-
+	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("checkUnstableModule", checkUnstableModuleMutator).Parallel()
+	})
 	ctx.Register(config)
 
 	return ctx, config
@@ -194,6 +209,153 @@
 	}
 }
 
+// Vintf module must have versions in release version
+func TestVintfWithoutVersionInRelease(t *testing.T) {
+	vintfWithoutVersionBp := `
+	aidl_interface {
+		name: "foo",
+		stability: "vintf",
+		srcs: [
+			"IFoo.aidl",
+		],
+	}`
+	expectedError := `module "foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false and PLATFORM_VERSION_CODENAME is REL`
+	testAidlError(t, expectedError, vintfWithoutVersionBp, setReleaseEnv())
+
+	ctx, _ := testAidl(t, vintfWithoutVersionBp)
+	assertModulesExists(t, ctx, "foo-java", "foo-cpp", "foo-ndk", "foo-ndk_platform")
+}
+
+// Check if using unstable version in release cause an error.
+func TestUnstableVersionUsageInRelease(t *testing.T) {
+	unstableVersionUsageInJavaBp := `
+	aidl_interface {
+		name: "foo",
+		versions: [
+			"1",
+		],
+		srcs: [
+			"IFoo.aidl",
+		],
+	}
+	java_library {
+		name: "bar",
+		libs: ["foo-unstable-java"],
+	}`
+
+	expectedError := `unstable-java is disallowed in release version because it is unstable.`
+	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
+	}))
+
+	testAidl(t, unstableVersionUsageInJavaBp, withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
+	}))
+
+	// A stable version can be used in release version
+	stableVersionUsageInJavaBp := `
+	aidl_interface {
+		name: "foo",
+		versions: [
+			"1",
+		],
+		srcs: [
+			"IFoo.aidl",
+		],
+	}
+	java_library {
+		name: "bar",
+		libs: ["foo-java"],
+	}`
+
+	testAidl(t, stableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
+	}))
+
+	testAidl(t, stableVersionUsageInJavaBp, withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
+	}))
+}
+
+// The module which has never been frozen and is not "unstable" is not allowed in release version.
+func TestNonVersionedModuleUsageInRelease(t *testing.T) {
+	nonVersionedModuleUsageInJavaBp := `
+	aidl_interface {
+		name: "foo",
+		srcs: [
+			"IFoo.aidl",
+		],
+	}
+
+	java_library {
+		name: "bar",
+		libs: ["foo-java"],
+	}`
+
+	expectedError := `"foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false and PLATFORM_VERSION_CODENAME is REL.`
+	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
+	testAidl(t, nonVersionedModuleUsageInJavaBp)
+
+	nonVersionedUnstableModuleUsageInJavaBp := `
+	aidl_interface {
+		name: "foo",
+		srcs: [
+			"IFoo.aidl",
+		],
+		unstable: true,
+	}
+
+	java_library {
+		name: "bar",
+		libs: ["foo-java"],
+	}`
+
+	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp, setReleaseEnv())
+	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp)
+}
+
+func TestUnstableModules(t *testing.T) {
+	testAidlError(t, `module "foo_interface": stability: must be empty when "unstable" is true`, `
+		aidl_interface {
+			name: "foo",
+			stability: "vintf",
+			unstable: true,
+			srcs: [
+				"IFoo.aidl",
+			],
+		}
+	`)
+
+	testAidlError(t, `module "foo_interface": versions: cannot have versions for an unstable interface`, `
+		aidl_interface {
+			name: "foo",
+			versions: [
+				"1",
+			],
+			unstable: true,
+			srcs: [
+				"IFoo.aidl",
+			],
+		}
+	`)
+
+	ctx, _ := testAidl(t, `
+		aidl_interface {
+			name: "foo",
+			unstable: true,
+			srcs: [
+				"IFoo.aidl",
+			],
+		}
+	`)
+
+	assertModulesExists(t, ctx, "foo-java", "foo-cpp", "foo-ndk", "foo-ndk_platform")
+}
+
 func TestCreatesModulesWithNoVersions(t *testing.T) {
 	ctx, _ := testAidl(t, `
 		aidl_interface {
diff --git a/build/properties.go b/build/properties.go
index 60d6a3f..eb52a52 100644
--- a/build/properties.go
+++ b/build/properties.go
@@ -39,6 +39,7 @@
 	Shared_libs               []string
 	Export_shared_lib_headers []string
 	Export_generated_headers  []string
+	Header_libs               []string
 	Sdk_version               *string
 	Stl                       *string
 	Cpp_std                   *string
diff --git a/docs/aidl-cpp.md b/docs/aidl-cpp.md
deleted file mode 100644
index aa97aa9..0000000
--- a/docs/aidl-cpp.md
+++ /dev/null
@@ -1,270 +0,0 @@
-# Generating C++ Binder Interfaces with `aidl-cpp`
-
-## Background
-
-“aidl” refers to several related but distinct concepts:
-
- - the AIDL interface [definition language](http://developer.android.com/guide/components/aidl.html)
- - .aidl files (which contain AIDL)
- - the aidl generator which transforms AIDL into client/server IPC interfaces
-
-The _aidl generator_ is a command line tool that generates client and server
-stubs for Binder interfaces from a specification in a file with the .aidl
-extension.  For Java interfaces, the executable is called `aidl` while for C++
-the binary is called `aidl-cpp`.  In this document, we’ll use AIDL to describe
-the language of .aidl files and _aidl generator_ to refer to the code generation
-tool that takes an .aidl file, parses the AIDL, and outputs code.
-
-Previously, the _aidl generator_ only generated Java interface/stub/proxy
-objects.  C++ Binder interfaces were handcrafted with various degrees of
-compatibility with the Java equivalents.  The Brillo project added support for
-generating C++ with the _aidl generator_.  This generated C++ is cross-language
-compatible (e.g. Java clients are tested to interoperate with native services).
-
-## Overview
-
-This document describes how C++ generation works with attention to:
-
- - build interface
- - cross-language type mapping
- - implementing a generated interface
- - C++ parcelables
- - cross-language error reporting
- - cross-language null reference handling
-
-## Detailed Design
-
-### Build Interface
-
-Write AIDL in .aidl files and add them to `LOCAL_SRC_FILES` in your Android.mk.
-If your build target is a binary (e.g. you include `$(BUILD_SHARED_LIBRARY)`),
-then the generated code will be C++, not Java.
-
-AIDL definitions should be hosted from the same repository as the
-implementation.  Any system that needs the definition will also need the
-implementation (for both parcelables and interface).  If there are multiple
-implementations (i.e. one in Java and one in C++), keep the definition with the
-native implementation.  Android
-[now has systems](https://developers.google.com/brillo/?hl=en) that run the
-native components of the system without the Java.
-
-If you use an import statement in your AIDL, even from the same package, you
-need to add a path to `LOCAL_AIDL_INCLUDES`.  This path should be relative to
-the root of the Android tree.  For instance, a file IFoo.aidl defining
-com.example.IFoo might sit in a folder hierarchy
-something/something-else/com/example/IFoo.aidl.  Then we would write:
-
-```
-LOCAL_AIDL_INCLUDES := something/something-else
-```
-
-Generated C++ ends up in nested namespaces corresponding to the interface’s
-package.  The generated header also corresponds to the interface package.  So
-com.example.IFoo becomes ::com::example::IFoo in header “com/example/IFoo.h”.
-
-Similar to how Java works, the suffix of the path to a .aidl file must match
-the package.  So if IFoo.aidl declares itself to be in package com.example, the
-folder structure (as given to `LOCAL_SRC_FILES`) must look like:
-`some/prefix/com/example/IFoo.aidl`.
-
-To generate code from .aidl files from another build target (e.g. another
-binary or java), just add a relative path to the .aidl files to
-`LOCAL_SRC_FILES`.  Remember that importing AIDL works the same, even for code
-in other directory hierarchies: add the include root path relative to the
-checkout root to `LOCAL_AIDL_INCLUDES`.
-
-### Type Mapping
-
-The following table summarizes the equivalent C++ types for common Java types
-and whether those types may be used as in/out/inout parameters in AIDL
-interfaces.
-
-| Java Type             | C++ Type            | inout | Notes                                                 |
-|-----------------------|---------------------|-------|-------------------------------------------------------|
-| boolean               | bool                | in    | "These 8 types are all considered primitives.         |
-| byte                  | int8\_t             | in    |                                                       |
-| char                  | char16\_t           | in    |                                                       |
-| int                   | int32\_t            | in    |                                                       |
-| long                  | int64\_t            | in    |                                                       |
-| float                 | float               | in    |                                                       |
-| double                | double              | in    |                                                       |
-| String                | String16            | in    | Supports null references.                             |
-| @utf8InCpp String     | std::string         | in    | @utf8InCpp causes UTF16 to UTF8 conversion in C++.    |
-| android.os.Parcelable | android::Parcelable | inout |                                                       |
-| T extends IBinder     | sp<T>               | in    |                                                       |
-| Arrays (T[])          | vector<T>           | inout | May contain only primitives, Strings and parcelables. |
-| List<String>          | vector<String16>    | inout |                                                       |
-| PersistableBundle     | PersistableBundle   | inout | binder/PersistableBundle.h                            |
-| List<IBinder>         | vector<sp<IBinder>> | inout |                                                       |
-| FileDescriptor        | unique_fd           | inout | android-base/unique_fd.h from libbase                 |
-
-Note that annotations may be placed at the interface level, as well as on a
-type by type basis.  Interface level annotations will be applied
-opportunistically and be overridden by per type annotations.  For instance, an
-interface marked @nullable will still not allow null int parameters.
-
-### Implementing a generated interface
-
-Given an interface declaration like:
-
-```
-package foo;
-
-import bar.IAnotherInterface;
-
-interface IFoo {
-  IAnotherInterface DoSomething(int count, out List<String> output);
-}
-```
-
-`aidl-cpp` will generate a C++ interface:
-
-```
-namespace foo {
-
-// Some headers have been omitted for clarity.
-#include <android/String16.h>
-#include <cstdint>
-#include <vector>
-#include <bar/IAnotherInterface.h>
-
-// Some class members have been omitted for clarity.
-class IFoo : public android::IInterface {
- public:
-  virtual android::binder::Status DoSomething(
-      int32_t count,
-      std::vector<android::String16>* output,
-      android::sp<bar::IAnotherInterface>* returned_value) = 0;
-};
-```
-
-Note that `aidl-cpp` will import headers for types used in the interface.  For
-imported types (e.g. parcelables and interfaces), it will import a header
-corresponding to the package/class name of the import.  For instance,
-`import bar.IAnotherInterface` causes aidl-cpp to generate
-`#include <bar/IAnotherInterface.h>`.
-
-When writing a service that implements this interface, write:
-
-```
-#include "foo/BnFoo.h"
-
-namespace unrelated_namespace {
-
-class MyFoo : public foo::BnFoo {
- public:
-  android::binder::Status DoSomething(
-      int32_t count,
-      std::vector<android::String16>* output,
-      android::sp<bar::IAnotherInterface>* returned_value) override {
-    for (int32_t i = 0; i < count; ++i) {
-      output->push_back(String16("..."));
-    }
-    *returned_value = new InstanceOfAnotherInterface;
-    return Status::ok();
-  }
-};  // class MyFoo
-
-}  // namespace unrelated_namespace
-```
-
-Note that the output values, `output` and `returned_value` are passed by
-pointer, and that this pointer is always valid.
-
-#### Dependencies
-
-The generated C++ code will use symbols from libbinder as well as libutils.
-AIDL files using the FileDescriptor type will also explicitly require
-libnativehelper, although this is likely a transitive dependency of the other
-two, and should be included automatically within the Android build tree
-regardless.
-
-### C++ Parcelables
-
-In Java, a parcelable should extend android.os.Parcelable and provide a static
-final CREATOR field that acts as a factory for new instances/arrays of
-instances of the parcelable.  In addition, in order to be used as an out
-parameter, a parcelable class must define a readFromParcel method.
-
-In C++, parcelables must implement android::Parcelable from binder/Parcelable.h
-in libbinder.  Parcelables must define a constructor that takes no arguments.
-In order to be used in arrays, a parcelable must implement a copy or move
-constructor (called implicitly in vector).
-
-The C++ generator needs to know what header defines the C++ parcelable.  It
-learns this from the `cpp_header` directive shown below.  The generator takes
-this string and uses it as the literal include statement in generated code.
-The idea here is that you generate your code once, link it into a library along
-with parcelable implementations, and export appropriate header paths.  This
-header include must make sense in the context of the Android.mk that compiles
-this generated code.
-
-```
-// ExampleParcelable.aidl
-package com.example.android;
-
-// Native types must be aliased at their declaration in the appropriate .aidl
-// file.  This allows multiple interfaces to use a parcelable and its C++
-// equivalent without duplicating the mapping between the C++ and Java types.
-// Generator will assume bar/foo.h declares class
-// com::example::android::ExampleParcelable
-parcelable ExampleParcelable cpp_header "bar/foo.h";
-```
-
-### Null Reference Handling
-
-The aidl generator for both C++ and Java languages has been expanded to
-understand nullable annotations.
-
-Given an interface definition like:
-
-```
-interface IExample {
-  void ReadStrings(String neverNull, in @nullable String maybeNull);
-};
-```
-
-the generated C++ header code looks like:
-
-```
-class IExample {
-  android::binder::Status ReadStrings(
-      const android::String16& in_neverNull,
-      const std::unique_ptr<android::String16>& in_maybeNull);
-};
-```
-
-Note that by default, the generated C++ passes a const reference to the value
-of a parameter and rejects null references with a NullPointerException sent
-back the caller.  Parameters marked with @nullable are passed by pointer,
-allowing native services to explicitly control whether they allow method
-overloading via null parameters.  Java stubs and proxies currently do nothing
-with the @nullable annotation.
-
-Consider an AIDL type `in @nullable List<String> bar`.  This type
-indicates that the remote caller may pass in a list of strings, and that both
-the list and any string in the list may be null.  This type will map to a C++
-type `unique_ptr<vector<unique_ptr<String16>>>* bar`.  In this case:
-
-  - `bar` is never null
-  - `*bar` might be null
-  - `(*bar)->empty()` could be true
-  - `(**bar)[0]` could be null (and so on)
-
-### Exception Reporting
-
-C++ methods generated by the aidl generator return `android::binder::Status`
-objects, rather than `android::status_t`.  This Status object allows generated
-C++ code to send and receive exceptions (an exception type and a String16 error
-message) since we do not use real exceptions in C++.  More background on Status
-objects can be found here.
-
-For legacy support and migration ease, the Status object includes a mechanism
-to report a `android::status_t`.  However, that return code is interpreted by a
-different code path and does not include a helpful String message.
-
-For situations where your native service needs to throw an error code specific
-to the service, use `Status::fromServiceSpecificError()`.  This kind of
-exception comes with a helpful message and an integer error code.  Make your
-error codes consistent across services by using interface constants (see
-below).
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index cc25657..da1e40e 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -271,9 +271,9 @@
   b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
 
   if (options.GenTraces()) {
-    b->AddLiteral(StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
-                               kTraceVarName, interface.GetName().c_str(),
-                               method.GetName().c_str()));
+    b->AddLiteral(
+        StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppClient\")",
+                     kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
   }
 
   if (options.GenLog()) {
@@ -552,6 +552,12 @@
       new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
   interface_check->OnTrue()->AddLiteral("break");
 
+  if (options.GenTraces()) {
+    b->AddLiteral(
+        StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppServer\")",
+                     kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
+  }
+
   // Deserialize each "in" parameter to the transaction.
   for (const auto& a: method.GetArguments()) {
     // Deserialization looks roughly like:
@@ -576,13 +582,6 @@
     }
   }
 
-  if (options.GenTraces()) {
-    b->AddStatement(new Statement(new MethodCall("atrace_begin",
-        ArgList{{"ATRACE_TAG_AIDL",
-        StringPrintf("\"%s::%s::cppServer\"",
-                     interface.GetName().c_str(),
-                     method.GetName().c_str())}})));
-  }
   const string bn_name = ClassName(interface, ClassNames::SERVER);
   if (options.GenLog()) {
     b->AddLiteral(GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */),
@@ -596,11 +595,6 @@
       StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
       ArgList(std::move(status_args)))));
 
-  if (options.GenTraces()) {
-    b->AddStatement(new Statement(new MethodCall("atrace_end",
-                                                 "ATRACE_TAG_AIDL")));
-  }
-
   if (options.GenLog()) {
     b->AddLiteral(GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
                                      true /* isServer */, false /* isNdk */),
@@ -1117,6 +1111,11 @@
     parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(out.str())));
   }
 
+  if (parcel.IsVintfStability()) {
+    parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(
+        new LiteralDecl("bool isStable() const override { return true; }\n")));
+  }
+
   unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
                                              ArgList("const ::android::Parcel* _aidl_parcel"),
                                              MethodDecl::IS_OVERRIDE | MethodDecl::IS_FINAL));
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index f4f2650..b7df190 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -421,7 +421,7 @@
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
   ::android::binder::Status _aidl_status;
-  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::Send::cppClient");
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::Send::cppClient");
   _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -474,7 +474,7 @@
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
   ::android::binder::Status _aidl_status;
-  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::Piff::cppClient");
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::Piff::cppClient");
   _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -500,7 +500,7 @@
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
   ::android::binder::Status _aidl_status;
-  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesABinder::cppClient");
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesABinder::cppClient");
   _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -537,7 +537,7 @@
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
   ::android::binder::Status _aidl_status;
-  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::NullableBinder::cppClient");
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::NullableBinder::cppClient");
   _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -570,7 +570,7 @@
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
   ::android::binder::Status _aidl_status;
-  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::StringListMethod::cppClient");
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::StringListMethod::cppClient");
   _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -611,7 +611,7 @@
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
   ::android::binder::Status _aidl_status;
-  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::BinderListMethod::cppClient");
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::BinderListMethod::cppClient");
   _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -652,7 +652,7 @@
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
   ::android::binder::Status _aidl_status;
-  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptor::cppClient");
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesAFileDescriptor::cppClient");
   _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -689,7 +689,7 @@
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
   ::android::binder::Status _aidl_status;
-  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptorArray::cppClient");
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesAFileDescriptorArray::cppClient");
   _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -1030,6 +1030,7 @@
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
     }
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::Send::cppServer");
     _aidl_ret_status = _aidl_data.readInt32Vector(&in_goes_in);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
@@ -1042,9 +1043,7 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
-    atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::Send::cppServer");
     ::android::binder::Status _aidl_status(Send(in_goes_in, &in_goes_in_and_out, &out_goes_out, &_aidl_return));
-    atrace_end(ATRACE_TAG_AIDL);
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
@@ -1073,13 +1072,12 @@
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
     }
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::Piff::cppServer");
     _aidl_ret_status = _aidl_data.readInt32(&in_times);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
-    atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::Piff::cppServer");
     ::android::binder::Status _aidl_status(Piff(in_times));
-    atrace_end(ATRACE_TAG_AIDL);
   }
   break;
   case ::android::IBinder::FIRST_CALL_TRANSACTION + 2 /* TakesABinder */:
@@ -1090,13 +1088,12 @@
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
     }
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesABinder::cppServer");
     _aidl_ret_status = _aidl_data.readStrongBinder(&in_f);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
-    atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesABinder::cppServer");
     ::android::binder::Status _aidl_status(TakesABinder(in_f, &_aidl_return));
-    atrace_end(ATRACE_TAG_AIDL);
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
@@ -1117,9 +1114,8 @@
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
     }
-    atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::NullableBinder::cppServer");
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::NullableBinder::cppServer");
     ::android::binder::Status _aidl_status(NullableBinder(&_aidl_return));
-    atrace_end(ATRACE_TAG_AIDL);
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
@@ -1142,13 +1138,12 @@
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
     }
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::StringListMethod::cppServer");
     _aidl_ret_status = _aidl_data.readString16Vector(&in_input);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
-    atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::StringListMethod::cppServer");
     ::android::binder::Status _aidl_status(StringListMethod(in_input, &out_output, &_aidl_return));
-    atrace_end(ATRACE_TAG_AIDL);
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
@@ -1175,13 +1170,12 @@
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
     }
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::BinderListMethod::cppServer");
     _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_input);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
-    atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::BinderListMethod::cppServer");
     ::android::binder::Status _aidl_status(BinderListMethod(in_input, &out_output, &_aidl_return));
-    atrace_end(ATRACE_TAG_AIDL);
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
@@ -1207,13 +1201,12 @@
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
     }
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesAFileDescriptor::cppServer");
     _aidl_ret_status = _aidl_data.readUniqueFileDescriptor(&in_f);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
-    atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptor::cppServer");
     ::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))) {
       break;
@@ -1235,13 +1228,12 @@
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
     }
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesAFileDescriptorArray::cppServer");
     _aidl_ret_status = _aidl_data.readUniqueFileDescriptorVector(&in_f);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
-    atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptorArray::cppServer");
     ::android::binder::Status _aidl_status(TakesAFileDescriptorArray(in_f, &_aidl_return));
-    atrace_end(ATRACE_TAG_AIDL);
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
diff --git a/generate_java.cpp b/generate_java.cpp
index 5d572a4..df98e26 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -119,6 +119,13 @@
   }
 
   std::ostringstream out;
+
+  if (parcel->IsVintfStability()) {
+    out << "public final boolean isStable() { return true; }\n";
+    parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
+  }
+
+  out.str("");
   out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
       << "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
   out << "  @Override\n";
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index aaa0471..dd629b2 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -419,10 +419,29 @@
                                std::shared_ptr<Variable> transact_data,
                                std::shared_ptr<Variable> transact_reply,
                                const AidlTypenames& typenames,
-                               std::shared_ptr<StatementBlock> statements,
+                               std::shared_ptr<StatementBlock> statement_block,
                                std::shared_ptr<StubClass> stubClass, const Options& options) {
-  std::shared_ptr<TryStatement> tryStatement;
-  std::shared_ptr<FinallyStatement> finallyStatement;
+  // try and finally
+  auto tryStatement = std::make_shared<TryStatement>();
+  auto finallyStatement = std::make_shared<FinallyStatement>();
+  auto& statements = statement_block;
+
+  if (options.GenTraces()) {
+    statements->Add(tryStatement);
+    statements->Add(finallyStatement);
+    statements = tryStatement->statements;
+    tryStatement->statements->Add(std::make_shared<MethodCall>(
+        std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
+        std::vector<std::shared_ptr<Expression>>{
+            std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
+            std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
+                                                      "::" + method.GetName() + "::server")}));
+    finallyStatement->statements->Add(std::make_shared<MethodCall>(
+        std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
+        std::vector<std::shared_ptr<Expression>>{
+            std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
+  }
+
   auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
 
   // interface token validation is the very first thing we do
@@ -467,33 +486,9 @@
     }
   }
 
-  if (options.GenTraces()) {
-    // try and finally, but only when generating trace code
-    tryStatement = std::make_shared<TryStatement>();
-    finallyStatement = std::make_shared<FinallyStatement>();
-
-    tryStatement->statements->Add(std::make_shared<MethodCall>(
-        std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
-        std::vector<std::shared_ptr<Expression>>{
-            std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
-            std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
-                                                      "::server")}));
-
-    finallyStatement->statements->Add(std::make_shared<MethodCall>(
-        std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
-        std::vector<std::shared_ptr<Expression>>{
-            std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
-  }
-
   // the real call
   if (method.GetType().GetName() == "void") {
-    if (options.GenTraces()) {
-      statements->Add(tryStatement);
-      tryStatement->statements->Add(realCall);
-      statements->Add(finallyStatement);
-    } else {
-      statements->Add(realCall);
-    }
+    statements->Add(realCall);
 
     if (!oneway) {
       // report that there were no exceptions
@@ -503,14 +498,7 @@
   } else {
     auto _result =
         std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
-    if (options.GenTraces()) {
-      statements->Add(std::make_shared<VariableDeclaration>(_result));
-      statements->Add(tryStatement);
-      tryStatement->statements->Add(std::make_shared<Assignment>(_result, realCall));
-      statements->Add(finallyStatement);
-    } else {
       statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
-    }
 
     if (!oneway) {
       // report that there were no exceptions
@@ -631,8 +619,8 @@
         std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
         std::vector<std::shared_ptr<Expression>>{
             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
-            std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
-                                                      "::client")}));
+            std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
+                                                      "::" + method.GetName() + "::client")}));
   }
 
   // the interface identifier token: the DESCRIPTOR constant, marshalled as a
@@ -868,7 +856,7 @@
            << "public synchronized String " << kGetInterfaceHash << "()"
            << " throws "
            << "android.os.RemoteException {\n"
-           << "  if (mCachedHash == \"-1\") {\n"
+           << "  if (\"-1\".equals(mCachedHash)) {\n"
            << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
            << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
            << "    try {\n"
@@ -1141,7 +1129,13 @@
   const string i_name = iface->GetCanonicalName();
   stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
       StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
-                   "  if (Stub.Proxy.sDefaultImpl == null && impl != null) {\n"
+                   "  // Only one user of this interface can use this function\n"
+                   "  // at a time. This is a heuristic to detect if two different\n"
+                   "  // users in the same process use this function.\n"
+                   "  if (Stub.Proxy.sDefaultImpl != null) {\n"
+                   "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
+                   "  }\n"
+                   "  if (impl != null) {\n"
                    "    Stub.Proxy.sDefaultImpl = impl;\n"
                    "    return true;\n"
                    "  }\n"
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index d08ac1b..0037b8a 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -182,25 +182,59 @@
   out << "#include <android/binder_stability.h>\n";
   out << "#endif  // BINDER_STABILITY_SUPPORT\n";
 
-  types.IterateTypes([&](const AidlDefinedType& other_defined_type) {
-    if (&other_defined_type == &defined_type) return;
-
-    if (other_defined_type.AsInterface() != nullptr) {
-      out << "#include <"
-          << 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::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::RAW, false /*use_os_sep*/) << ">\n";
-    } else {
-      AIDL_FATAL(defined_type) << "Unrecognized type.";
+  auto headerFilePath = [&types](const AidlTypeSpecifier& typespec) -> std::string {
+    const AidlDefinedType* type = types.TryGetDefinedType(typespec.GetName());
+    if (type == nullptr) {
+      // could be a primitive type.
+      return "";
     }
-  });
+
+    if (type->AsInterface() != nullptr) {
+      return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
+    } else if (type->AsStructuredParcelable() != nullptr) {
+      return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
+    } else if (type->AsParcelable() != nullptr) {
+      return type->AsParcelable()->GetCppHeader();
+    } else if (type->AsEnumDeclaration() != nullptr) {
+      return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
+    } else {
+      AIDL_FATAL(*type) << "Unrecognized type.";
+      return "";
+    }
+  };
+
+  std::set<std::string> includes;
+
+  const AidlInterface* interface = defined_type.AsInterface();
+  if (interface != nullptr) {
+    for (const auto& method : interface->GetMethods()) {
+      includes.insert(headerFilePath(method->GetType()));
+      for (const auto& argument : method->GetArguments()) {
+        includes.insert(headerFilePath(argument->GetType()));
+      }
+    }
+  }
+
+  const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
+  if (parcelable != nullptr) {
+    for (const auto& field : parcelable->GetFields()) {
+      includes.insert(headerFilePath(field->GetType()));
+    }
+  }
+
+  const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
+  if (enum_decl != nullptr) {
+    includes.insert(headerFilePath(enum_decl->GetBackingType()));
+  }
+
+  for (const auto& path : includes) {
+    if (path == "") {
+      continue;
+    }
+    out << "#include <" << path << ">\n";
+  }
 }
+
 static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
                                    const AidlDefinedType& /*defined_type*/) {
   out << "#include <android/binder_parcel_utils.h>\n";
@@ -325,6 +359,11 @@
     out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
                                     false /* isServer */, true /* isNdk */);
   }
+  if (options.GenTraces()) {
+    out << "ScopedTrace _aidl_trace(\"AIDL::" << Options::LanguageToString(options.TargetLanguage())
+        << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
+        << "::client\");\n";
+  }
 
   out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
   StatusCheckGoto(out);
@@ -362,8 +401,9 @@
   out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
   out << iface << "::getDefaultImpl()) {\n";
   out.Indent();
-  out << "return " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
+  out << "_aidl_status = " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
   out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
+  out << "goto _aidl_status_return;\n";
   out.Dedent();
   out << "}\n";
 
@@ -373,7 +413,7 @@
     out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
     StatusCheckGoto(out);
 
-    out << "if (!AStatus_isOk(_aidl_status.get())) return _aidl_status;\n\n";
+    out << "if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;\n";
   }
 
   if (method.GetType().GetName() != "void") {
@@ -396,11 +436,13 @@
 
   out << "_aidl_error:\n";
   out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
+  out << "_aidl_status_return:\n";
   if (options.GenLog()) {
     out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
                                    method, "_aidl_status", "_aidl_return", false /* isServer */,
                                    true /* isNdk */);
   }
+
   out << "return _aidl_status;\n";
   out.Dedent();
   out << "}\n";
@@ -419,6 +461,11 @@
     out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
   }
   out << "\n";
+  if (options.GenTraces()) {
+    out << "ScopedTrace _aidl_trace(\"AIDL::" << Options::LanguageToString(options.TargetLanguage())
+        << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
+        << "::server\");\n";
+  }
 
   for (const auto& arg : method.GetArguments()) {
     const std::string var_name = cpp::BuildVarName(*arg);
@@ -476,7 +523,19 @@
                          const AidlInterface& defined_type, const Options& options) {
   const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
   const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
-
+  if (options.GenTraces()) {
+    out << "class ScopedTrace {\n";
+    out.Indent();
+    out << "public:\n"
+        << "inline ScopedTrace(const char* name) {\n"
+        << "ATrace_beginSection(name);\n"
+        << "}\n"
+        << "inline ~ScopedTrace() {\n"
+        << "ATrace_endSection();\n"
+        << "}\n";
+    out.Dedent();
+    out << "};\n";
+  }
   out << "static binder_status_t "
       << "_aidl_onTransact"
       << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
@@ -623,7 +682,11 @@
   // defintion for static member setDefaultImpl
   out << "bool " << clazz << "::setDefaultImpl(std::shared_ptr<" << clazz << "> impl) {\n";
   out.Indent();
-  out << "if (!" << clazz << "::default_impl && impl) {\n";
+  out << "// Only one user of this interface can use this function\n";
+  out << "// at a time. This is a heuristic to detect if two different\n";
+  out << "// users in the same process use this function.\n";
+  out << "assert(!" << clazz << "::default_impl);\n";
+  out << "if (impl) {\n";
   out.Indent();
   out << clazz << "::default_impl = impl;\n";
   out << "return true;\n";
@@ -705,6 +768,9 @@
     out << "#include <chrono>\n";
     out << "#include <sstream>\n";
   }
+  if (options.GenTraces()) {
+    out << "#include <android/trace.h>\n";
+  }
   out << "\n";
   EnterNdkNamespace(out, defined_type);
   out << "class " << clazz << " : public ::ndk::BpCInterface<"
@@ -881,6 +947,9 @@
   out << "\n";
   out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
   out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
+
+  out << "static const bool _aidl_is_stable = "
+      << (defined_type.IsVintfStability() ? "true" : "false") << ";\n";
   out.Dedent();
   out << "};\n";
   LeaveNdkNamespace(out, defined_type);
diff --git a/run_integration_tests.sh b/run_integration_tests.sh
new file mode 100755
index 0000000..066faad
--- /dev/null
+++ b/run_integration_tests.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+# 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.
+
+set -ex
+
+# TODO(b/156942077): when this test was converted to atest, we lost the ability
+# to see test results on stdout, and we can't print out the gtest results on
+# stderr because it breaks python test parsing. So, this file is added to help
+# run integration tests.
+
+$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
+    MODULES-IN-system-tools-aidl
+
+adb root
+adb sync data
+adb install -r \
+    ${ANDROID_PRODUCT_OUT}/testcases/aidl_test_services/x86/aidl_test_services.apk
+
+${ANDROID_BUILD_TOP}/system/tools/aidl/tests/aidl_integration_test.py
diff --git a/tests/aidl_integration_test.py b/tests/aidl_integration_test.py
index ffd26a5..fe67ae4 100755
--- a/tests/aidl_integration_test.py
+++ b/tests/aidl_integration_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import pipes
 import subprocess
@@ -114,8 +114,8 @@
         self.host.run('killall %s' % self.binary, ignore_status=True)
     def run(self):
         result = self.host.run(self.binary, ignore_status=True)
+        print(result.printable_string())
         if result.exit_status:
-            print(result.printable_string())
             raise TestFail('%s returned status code %d' %
                            (self.binary, result.exit_status))
 
@@ -141,16 +141,16 @@
                                 JAVA_LOG_FILE, JAVA_SUCCESS_SENTINEL,
                                 JAVA_FAILURE_SENTINEL),
                                ignore_status=True)
+        print(result.printable_string())
         if result.exit_status:
-            print(result.printable_string())
             raise TestFail('Java client did not complete successfully.')
 
 def supported_bitnesses(host):
     bitnesses = []
-    if host.run('ls /data/nativetest/', ignore_status=True).exit_status == 0:
-        bitnesses = [BITNESS_32]
-    if host.run('ls /data/nativetest64/', ignore_status=True).exit_status == 0:
-        bitnesses += [BITNESS_64]
+    for bitness in [BITNESS_32, BITNESS_64]:
+        native_client = NATIVE_TEST_CLIENT_FOR_BITNESS % bitness
+        if host.run('ls %s' % native_client, ignore_status=True).exit_status == 0:
+            bitnesses += [bitness]
     return bitnesses
 
 # tests added dynamically below
diff --git a/tests/aidl_test_client.cpp b/tests/aidl_test_client.cpp
index 678edc5..c95bc90 100644
--- a/tests/aidl_test_client.cpp
+++ b/tests/aidl_test_client.cpp
@@ -14,107 +14,42 @@
  * limitations under the License.
  */
 
-#include <iostream>
-
-#include <android-base/logging.h>
-#include <binder/IServiceManager.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-#include "android/aidl/tests/ITestService.h"
+#include "aidl_test_client.h"
 
 #include "aidl_test_client_defaultimpl.h"
 #include "aidl_test_client_file_descriptors.h"
 #include "aidl_test_client_nullables.h"
-#include "aidl_test_client_parcelables.h"
 #include "aidl_test_client_primitives.h"
 #include "aidl_test_client_service_exceptions.h"
 #include "aidl_test_client_utf8_strings.h"
 
-// libutils:
-using android::OK;
-using android::sp;
-using android::status_t;
-using android::String16;
+#include <android-base/logging.h>
 
-// libbinder:
-using android::getService;
-
-// generated
-using android::aidl::tests::ITestService;
-
-using std::cerr;
-using std::cout;
-using std::endl;
-
-namespace android {
-namespace aidl {
-namespace tests {
-namespace client {
-
-const char kServiceName[] = "android.aidl.tests.ITestService";
-
-bool GetService(sp<ITestService>* service) {
-  cout << "Retrieving test service binder" << endl;
-  status_t status = getService(String16(kServiceName), service);
-  if (status != OK) {
-    cerr << "Failed to get service binder: '" << kServiceName
-         << "' status=" << status << endl;
-    return false;
-  }
-  return true;
-}
-
-}  // namespace client
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
-
-/* Runs all the test cases in aidl_test_client_*.cpp files. */
-int main(int /* argc */, char * argv []) {
-  android::base::InitLogging(argv, android::base::StderrLogger);
-  sp<ITestService> service;
+// These tests were written without gtest, and not all have been converted to
+// gtest. Places which haven't been converted are still included as part of this
+// test here.
+TEST_F(AidlTest, UnconvertedTests) {
   namespace client_tests = android::aidl::tests::client;
 
-  if (!client_tests::GetService(&service)) return 1;
+  EXPECT_TRUE(client_tests::ConfirmPrimitiveRepeat(service));
+  EXPECT_TRUE(client_tests::ConfirmReverseArrays(service));
+  EXPECT_TRUE(client_tests::ConfirmReverseLists(service));
+  EXPECT_TRUE(client_tests::ConfirmReverseBinderLists(service));
+  EXPECT_TRUE(client_tests::ConfirmIntfConstantExpressions(service));
+  EXPECT_TRUE(client_tests::ConfirmFileDescriptors(service));
+  EXPECT_TRUE(client_tests::ConfirmFileDescriptorArrays(service));
+  EXPECT_TRUE(client_tests::ConfirmParcelFileDescriptors(service));
+  EXPECT_TRUE(client_tests::ConfirmParcelFileDescriptorArrays(service));
+  EXPECT_TRUE(client_tests::ConfirmServiceSpecificExceptions(service));
+  EXPECT_TRUE(client_tests::ConfirmNullables(service));
+  EXPECT_TRUE(client_tests::ConfirmUtf8InCppStringRepeat(service));
+  EXPECT_TRUE(client_tests::ConfirmUtf8InCppStringArrayReverse(service));
+  EXPECT_TRUE(client_tests::ConfirmUtf8InCppStringListReverse(service));
+  EXPECT_TRUE(client_tests::ConfirmDefaultImpl(service));
+}
 
-  if (!client_tests::ConfirmPrimitiveRepeat(service)) return 1;
-
-  if (!client_tests::ConfirmReverseArrays(service)) return 1;
-
-  if (!client_tests::ConfirmReverseLists(service)) return 1;
-
-  if (!client_tests::ConfirmReverseBinderLists(service)) return 1;
-
-  if (!client_tests::ConfirmSimpleParcelables(service)) return 1;
-
-  if (!client_tests::ConfirmPersistableBundles(service)) return 1;
-
-  if (!client_tests::ConfirmIntfConstantExpressions(service)) return 1;
-
-  if (!client_tests::ConfirmStructuredParcelables(service)) return 1;
-
-  if (!client_tests::ConfirmStructuredParcelablesEquality(service)) return 1;
-
-  if (!client_tests::ConfirmFileDescriptors(service)) return 1;
-
-  if (!client_tests::ConfirmFileDescriptorArrays(service)) return 1;
-
-  if (!client_tests::ConfirmParcelFileDescriptors(service)) return 1;
-
-  if (!client_tests::ConfirmParcelFileDescriptorArrays(service)) return 1;
-
-  if (!client_tests::ConfirmServiceSpecificExceptions(service)) return 1;
-
-  if (!client_tests::ConfirmNullables(service)) return 1;
-
-  if (!client_tests::ConfirmUtf8InCppStringRepeat(service)) return 1;
-
-  if (!client_tests::ConfirmUtf8InCppStringArrayReverse(service)) return 1;
-
-  if (!client_tests::ConfirmUtf8InCppStringListReverse(service)) return 1;
-
-  if (!client_tests::ConfirmDefaultImpl(service)) return 1;
-
-  return 0;
+int main(int argc, char* argv[]) {
+  android::base::InitLogging(argv, android::base::StderrLogger);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
 }
diff --git a/tests/aidl_test_client.h b/tests/aidl_test_client.h
new file mode 100644
index 0000000..bdd0b7c
--- /dev/null
+++ b/tests/aidl_test_client.h
@@ -0,0 +1,40 @@
+/*
+ * 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 <android/aidl/tests/ITestService.h>
+#include <binder/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <utils/String16.h>
+
+using android::sp;
+using android::aidl::tests::ITestService;
+
+class AidlTest : public testing::Test {
+ public:
+  void SetUp() override {
+    using android::getService;
+    using android::OK;
+    using android::String16;
+
+    static const char kServiceName[] = "android.aidl.tests.ITestService";
+    ASSERT_EQ(OK, getService(String16(kServiceName), &service));
+    ASSERT_NE(nullptr, service);
+  }
+
+  sp<ITestService> service;
+};
diff --git a/tests/aidl_test_client_parcelables.cpp b/tests/aidl_test_client_parcelables.cpp
index cc89270..7152acc 100644
--- a/tests/aidl_test_client_parcelables.cpp
+++ b/tests/aidl_test_client_parcelables.cpp
@@ -14,84 +14,55 @@
  * limitations under the License.
  */
 
-#include "aidl_test_client_parcelables.h"
+#include "aidl_test_client.h"
 
-#include <iostream>
 #include <vector>
 
-// libutils:
+using android::IInterface;
 using android::sp;
-
-// libbinder:
-using android::binder::Status;
-
-// generated
+using android::String16;
 using android::aidl::tests::ConstantExpressionEnum;
+using android::aidl::tests::INamedCallback;
+using android::aidl::tests::IntEnum;
 using android::aidl::tests::ITestService;
 using android::aidl::tests::SimpleParcelable;
+using android::aidl::tests::StructuredParcelable;
+using android::binder::Status;
 using android::os::PersistableBundle;
-
-using std::cout;
-using std::endl;
 using std::vector;
 
-namespace android {
-namespace aidl {
-namespace tests {
-namespace client {
-
-bool ConfirmSimpleParcelables(const sp<ITestService>& s) {
-  cout << "Confirming passing and returning SimpleParcelable objects works."
-       << endl;
-
+TEST_F(AidlTest, RepeatSimpleParcelable) {
   SimpleParcelable input("Booya", 42);
   SimpleParcelable out_param, returned;
-  Status status = s->RepeatSimpleParcelable(input, &out_param, &returned);
-  if (!status.isOk()) {
-    cout << "Binder call failed." << endl;
-    return false;
-  }
-  if (input != out_param || input != returned) {
-    cout << "Failed to repeat SimpleParcelable objects." << endl;
-    return false;
-  }
+  Status status = service->RepeatSimpleParcelable(input, &out_param, &returned);
+  ASSERT_TRUE(status.isOk()) << status.toString8();
+  EXPECT_EQ(input, out_param);
+  EXPECT_EQ(input, returned);
+}
 
-  cout << "Attempting to reverse an array of SimpleParcelable objects." << endl;
+TEST_F(AidlTest, ReverseSimpleParcelable) {
   const vector<SimpleParcelable> original{SimpleParcelable("first", 0),
                                           SimpleParcelable("second", 1),
                                           SimpleParcelable("third", 2)};
   vector<SimpleParcelable> repeated;
   vector<SimpleParcelable> reversed;
-  status = s->ReverseSimpleParcelables(original, &repeated, &reversed);
-  if (!status.isOk()) {
-    cout << "Binder call failed." << endl;
-    return false;
-  }
-  std::reverse(reversed.begin(), reversed.end());
-  if (repeated != original || reversed != original) {
-    cout << "Failed to reverse an array of SimpleParcelable objects." << endl;
-    return false;
-  }
+  Status status = service->ReverseSimpleParcelables(original, &repeated, &reversed);
+  ASSERT_TRUE(status.isOk()) << status.toString8();
 
-  return true;
+  EXPECT_EQ(repeated, original);
+
+  std::reverse(reversed.begin(), reversed.end());
 }
 
-bool ConfirmPersistableBundles(const sp<ITestService>& s) {
-  cout << "Confirming passing and returning PersistableBundle objects works."
-       << endl;
-
+TEST_F(AidlTest, ConfirmPersistableBundles) {
   PersistableBundle empty_bundle, returned;
-  Status status = s->RepeatPersistableBundle(empty_bundle, &returned);
-  if (!status.isOk()) {
-    cout << "Binder call failed for empty PersistableBundle." << endl;
-    return false;
-  }
-  if (empty_bundle != returned) {
-    cout << "Failed to repeat empty PersistableBundle." << endl;
-    return false;
-  }
+  Status status = service->RepeatPersistableBundle(empty_bundle, &returned);
+  ASSERT_TRUE(status.isOk()) << status.toString8();
+  EXPECT_EQ(empty_bundle, returned);
+}
 
-  PersistableBundle non_empty_bundle;
+TEST_F(AidlTest, ConfirmPersistableBundlesNonEmpty) {
+  PersistableBundle non_empty_bundle, returned;
   non_empty_bundle.putBoolean(String16("test_bool"), false);
   non_empty_bundle.putInt(String16("test_int"), 33);
   non_empty_bundle.putLong(String16("test_long"), 34359738368L);
@@ -110,18 +81,12 @@
   non_empty_bundle.putPersistableBundle(String16("test_persistable_bundle"),
                                         nested_bundle);
 
-  status = s->RepeatPersistableBundle(non_empty_bundle, &returned);
-  if (!status.isOk()) {
-    cout << "Binder call failed. " << endl;
-    return false;
-  }
-  if (non_empty_bundle != returned) {
-    cout << "Failed to repeat PersistableBundle object." << endl;
-    return false;
-  }
+  Status status = service->RepeatPersistableBundle(non_empty_bundle, &returned);
+  ASSERT_TRUE(status.isOk()) << status.toString8();
+  EXPECT_EQ(non_empty_bundle, returned);
+}
 
-  cout << "Attempting to reverse an array of PersistableBundle objects."
-       << endl;
+TEST_F(AidlTest, ReversePersistableBundles) {
   PersistableBundle first;
   PersistableBundle second;
   PersistableBundle third;
@@ -132,275 +97,113 @@
 
   vector<PersistableBundle> repeated;
   vector<PersistableBundle> reversed;
-  status = s->ReversePersistableBundles(original, &repeated, &reversed);
-  if (!status.isOk()) {
-    cout << "Binder call failed." << endl;
-    return false;
-  }
-  std::reverse(reversed.begin(), reversed.end());
-  if (repeated != original || reversed != original) {
-    cout << "Failed to reverse an array of PersistableBundle objects." << endl;
-    return false;
-  }
+  Status status = service->ReversePersistableBundles(original, &repeated, &reversed);
+  ASSERT_TRUE(status.isOk()) << status.toString8();
 
-  return true;
+  EXPECT_EQ(repeated, original);
+
+  std::reverse(reversed.begin(), reversed.end());
+  EXPECT_EQ(reversed, original);
 }
 
-bool ConfirmStructuredParcelablesEquality(const sp<ITestService>& s) {
+TEST_F(AidlTest, StructuredParcelableEquality) {
+  // TODO: break up equality tests, these are hard to read, because you need to
+  // keep the state of the parcelables in mind
   StructuredParcelable parcelable1;
   StructuredParcelable parcelable2;
 
   parcelable1.f = 11;
   parcelable2.f = 11;
 
-  s->FillOutStructuredParcelable(&parcelable1);
-  s->FillOutStructuredParcelable(&parcelable2);
+  service->FillOutStructuredParcelable(&parcelable1);
+  service->FillOutStructuredParcelable(&parcelable2);
 
   sp<INamedCallback> callback1;
   sp<INamedCallback> callback2;
-  s->GetOtherTestService(String16("callback1"), &callback1);
-  s->GetOtherTestService(String16("callback2"), &callback2);
+  service->GetOtherTestService(String16("callback1"), &callback1);
+  service->GetOtherTestService(String16("callback2"), &callback2);
 
   parcelable1.ibinder = IInterface::asBinder(callback1);
   parcelable2.ibinder = IInterface::asBinder(callback1);
 
-  if (parcelable1 != parcelable2) {
-    cout << "parcelable1 and parcelable2 should be same." << endl;
-    return false;
-  }
+  EXPECT_EQ(parcelable1, parcelable2);
+
   parcelable1.f = 0;
-  if (parcelable1 >= parcelable2) {
-    cout << "parcelable1 and parcelable2 should be different because of shouldContainThreeFs"
-         << endl;
-    return false;
-  }
+  EXPECT_LT(parcelable1, parcelable2);
   parcelable1.f = 11;
 
   parcelable1.shouldBeJerry = "Jarry";
-  if (!(parcelable1 < parcelable2)) {
-    cout << "parcelable1 and parcelable2 should be different because of shouldContainThreeFs"
-         << endl;
-    return false;
-  }
+  EXPECT_LT(parcelable1, parcelable2);
   parcelable1.shouldBeJerry = "Jerry";
 
   parcelable2.shouldContainThreeFs = {};
-  if (parcelable1 <= parcelable2) {
-    cout << "parcelable1 and parcelable2 should be different because of shouldContainThreeFs"
-         << endl;
-    return false;
-  }
+  EXPECT_GT(parcelable1, parcelable2);
   parcelable2.shouldContainThreeFs = {parcelable2.f, parcelable2.f, parcelable2.f};
 
   parcelable2.shouldBeIntBar = IntEnum::FOO;
-  if (!(parcelable1 > parcelable2)) {
-    cout << "parcelable1 and parcelable2 should be different because of shouldBeIntBar" << endl;
-    return false;
-  }
+  EXPECT_GT(parcelable1, parcelable2);
   parcelable2.shouldBeIntBar = IntEnum::BAR;
 
   parcelable2.ibinder = IInterface::asBinder(callback2);
-  if (parcelable1 == parcelable2) {
-    cout << "parcelable1 and parcelable2 should be different because of ibinder" << endl;
-    return false;
-  }
-  return true;
+  EXPECT_NE(parcelable1, parcelable2);
 }
 
-bool ConfirmStructuredParcelables(const sp<ITestService>& s) {
-  bool success = true;
+TEST_F(AidlTest, ConfirmStructuredParcelables) {
   constexpr int kDesiredValue = 23;
 
   StructuredParcelable parcelable;
   parcelable.f = kDesiredValue;
 
-  if (parcelable.stringDefaultsToFoo != String16("foo")) {
-    cout << "stringDefaultsToFoo should be 'foo' but is " << parcelable.stringDefaultsToFoo << endl;
-    return false;
-  }
-  if (parcelable.byteDefaultsToFour != 4) {
-    cout << "byteDefaultsToFour should be 4 but is " << parcelable.byteDefaultsToFour << endl;
-    return false;
-  }
-  if (parcelable.intDefaultsToFive != 5) {
-    cout << "intDefaultsToFive should be 5 but is " << parcelable.intDefaultsToFive << endl;
-    return false;
-  }
-  if (parcelable.longDefaultsToNegativeSeven != -7) {
-    cout << "longDefaultsToNegativeSeven should be -7 but is "
-         << parcelable.longDefaultsToNegativeSeven << endl;
-    return false;
-  }
-  if (!parcelable.booleanDefaultsToTrue) {
-    cout << "booleanDefaultsToTrue isn't true" << endl;
-    return false;
-  }
-  if (parcelable.charDefaultsToC != 'C') {
-    cout << "charDefaultsToC is " << parcelable.charDefaultsToC << endl;
-    return false;
-  }
-  if (parcelable.floatDefaultsToPi != 3.14f) {
-    cout << "floatDefaultsToPi is " << parcelable.floatDefaultsToPi << endl;
-    return false;
-  }
-  if (parcelable.doubleWithDefault != -3.14e17) {
-    cout << "doubleWithDefault is " << parcelable.doubleWithDefault << " but should be -3.14e17"
-         << endl;
-    return false;
-  }
-  if (parcelable.arrayDefaultsTo123.size() != 3) {
-    cout << "arrayDefaultsTo123 is of length " << parcelable.arrayDefaultsTo123.size() << endl;
-    return false;
-  }
-  for (int i = 0; i < 3; i++) {
-    if (parcelable.arrayDefaultsTo123[i] != i + 1) {
-      cout << "arrayDefaultsTo123[" << i << "] is " << parcelable.arrayDefaultsTo123[i]
-           << " but should be " << i + 1 << endl;
-      return false;
-    }
-  }
-  if (!parcelable.arrayDefaultsToEmpty.empty()) {
-    cout << "arrayDefaultsToEmpty is not empty " << parcelable.arrayDefaultsToEmpty.size() << endl;
-    return false;
-  }
+  EXPECT_EQ(parcelable.stringDefaultsToFoo, String16("foo"));
+  EXPECT_EQ(parcelable.byteDefaultsToFour, 4);
+  EXPECT_EQ(parcelable.intDefaultsToFive, 5);
+  EXPECT_EQ(parcelable.longDefaultsToNegativeSeven, -7);
+  EXPECT_EQ(parcelable.booleanDefaultsToTrue, true);
+  EXPECT_EQ(parcelable.charDefaultsToC, 'C');
+  EXPECT_TRUE(parcelable.floatDefaultsToPi == 3.14f) << parcelable.floatDefaultsToPi;
+  EXPECT_TRUE(parcelable.doubleWithDefault == -3.14e17) << parcelable.doubleWithDefault;
 
-  s->FillOutStructuredParcelable(&parcelable);
+  ASSERT_EQ(parcelable.arrayDefaultsTo123.size(), 3u);
+  EXPECT_EQ(parcelable.arrayDefaultsTo123[0], 1);
+  EXPECT_EQ(parcelable.arrayDefaultsTo123[1], 2);
+  EXPECT_EQ(parcelable.arrayDefaultsTo123[2], 3);
+  EXPECT_TRUE(parcelable.arrayDefaultsToEmpty.empty());
 
-  if (parcelable.shouldContainThreeFs.size() != 3) {
-    cout << "shouldContainThreeFs is of length " << parcelable.shouldContainThreeFs.size() << endl;
-    return false;
-  }
+  service->FillOutStructuredParcelable(&parcelable);
 
-  for (int i = 0; i < 3; i++) {
-    if (parcelable.shouldContainThreeFs[i] != kDesiredValue) {
-      cout << "shouldContainThreeFs[" << i << "] is " << parcelable.shouldContainThreeFs[i]
-           << " but should be " << kDesiredValue << endl;
-      return false;
-    }
-  }
+  ASSERT_EQ(parcelable.shouldContainThreeFs.size(), 3u);
+  EXPECT_EQ(parcelable.shouldContainThreeFs[0], kDesiredValue);
+  EXPECT_EQ(parcelable.shouldContainThreeFs[1], kDesiredValue);
+  EXPECT_EQ(parcelable.shouldContainThreeFs[2], kDesiredValue);
 
-  if (parcelable.shouldBeJerry != "Jerry") {
-    cout << "shouldBeJerry should be 'Jerry' but is " << parcelable.shouldBeJerry << endl;
-    return false;
-  }
-
-  if (parcelable.int32_min != INT32_MIN) {
-    cout << "int32_min should be " << INT32_MIN << "but is " << parcelable.int32_min << endl;
-    return false;
-  }
-
-  if (parcelable.int32_max != INT32_MAX) {
-    cout << "int32_max should be " << INT32_MAX << "but is " << parcelable.int32_max << endl;
-    return false;
-  }
-
-  if (parcelable.int64_max != INT64_MAX) {
-    cout << "int64_max should be " << INT64_MAX << "but is " << parcelable.int64_max << endl;
-    return false;
-  }
-
-  if (parcelable.hexInt32_neg_1 != -1) {
-    cout << "hexInt32_neg_1 should be -1 but is " << parcelable.hexInt32_neg_1 << endl;
-    return false;
-  }
+  EXPECT_EQ(parcelable.shouldBeJerry, "Jerry");
+  EXPECT_EQ(parcelable.int32_min, INT32_MIN);
+  EXPECT_EQ(parcelable.int32_max, INT32_MAX);
+  EXPECT_EQ(parcelable.int64_max, INT64_MAX);
+  EXPECT_EQ(parcelable.hexInt32_neg_1, -1);
 
   for (size_t ndx = 0; ndx < parcelable.int32_1.size(); ndx++) {
-    if (parcelable.int32_1[ndx] != 1) {
-      cout << "int32_1[" << ndx << "] should be 1 but is " << parcelable.int32_1[ndx] << endl;
-      success = false;
-    }
-  }
-  if (!success) {
-    return false;
+    EXPECT_EQ(parcelable.int32_1[ndx], 1) << ndx;
   }
 
   for (size_t ndx = 0; ndx < parcelable.int64_1.size(); ndx++) {
-    if (parcelable.int64_1[ndx] != 1) {
-      cout << "int64_1[" << ndx << "] should be 1 but is " << parcelable.int64_1[ndx] << endl;
-      success = false;
-    }
-  }
-  if (!success) {
-    return false;
+    EXPECT_EQ(parcelable.int64_1[ndx], 1) << ndx;
   }
 
-  if (static_cast<int>(parcelable.hexInt32_pos_1) != 1) {
-    cout << "hexInt32_pos_1 should be 1 but is " << parcelable.hexInt32_pos_1 << endl;
-    return false;
-  }
+  EXPECT_EQ(parcelable.hexInt32_pos_1, 1);
+  EXPECT_EQ(parcelable.hexInt64_pos_1, 1);
 
-  if (parcelable.hexInt64_pos_1 != 1) {
-    cout << "hexInt64_pos_1 should be 1 but is " << parcelable.hexInt64_pos_1 << endl;
-    return false;
-  }
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_1), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_2), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_3), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_4), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_5), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_6), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_7), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_8), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_9), 1);
+  EXPECT_EQ(static_cast<int>(parcelable.const_exprs_10), 1);
 
-  if (static_cast<int>(parcelable.const_exprs_1) != 1) {
-    cout << "parcelable.const_exprs_1 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_1) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_2) != 1) {
-    cout << "parcelable.const_exprs_2 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_2) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_3) != 1) {
-    cout << "parcelable.const_exprs_3 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_3) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_4) != 1) {
-    cout << "parcelable.const_exprs_4 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_4) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_5) != 1) {
-    cout << "parcelable.const_exprs_5 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_5) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_6) != 1) {
-    cout << "parcelable.const_exprs_6 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_6) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_7) != 1) {
-    cout << "parcelable.const_exprs_7 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_7) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_8) != 1) {
-    cout << "parcelable.const_exprs_8 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_8) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_9) != 1) {
-    cout << "parcelable.const_exprs_9 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_9) << endl;
-    return false;
-  }
-  if (static_cast<int>(parcelable.const_exprs_10) != 1) {
-    cout << "parcelable.const_exprs_10 should be 1 but is "
-         << static_cast<int>(parcelable.const_exprs_10) << endl;
-    return false;
-  }
-
-  if (parcelable.addString1 != "hello world!") {
-    cout << "parcelable.addString1 should be \"hello world!\" but is \"" << parcelable.addString1
-         << "\"" << endl;
-    return false;
-  }
-  if (parcelable.addString2 != "The quick brown fox jumps over the lazy dog.") {
-    cout << "parcelable.addString2 should be \"The quick brown fox jumps over the lazy dog.\""
-            " but is \""
-         << parcelable.addString2 << "\"" << endl;
-    return false;
-  }
-
-  return true;
+  EXPECT_EQ(parcelable.addString1, "hello world!");
+  EXPECT_EQ(parcelable.addString2, "The quick brown fox jumps over the lazy dog.");
 }
-
-}  // namespace client
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
diff --git a/tests/aidl_test_client_parcelables.h b/tests/aidl_test_client_parcelables.h
deleted file mode 100644
index 3031ad4..0000000
--- a/tests/aidl_test_client_parcelables.h
+++ /dev/null
@@ -1,40 +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.
- */
-
-#ifndef ANDROID_AIDL_TESTS_CLIENT_PARCELABLES_H
-#define ANDROID_AIDL_TESTS_CLIENT_PARCELABLES_H
-
-#include <utils/StrongPointer.h>
-
-#include "android/aidl/tests/ITestService.h"
-
-// Tests for passing and returning parcelable types.
-namespace android {
-namespace aidl {
-namespace tests {
-namespace client {
-
-bool ConfirmSimpleParcelables(const sp<ITestService>& s);
-bool ConfirmPersistableBundles(const sp<ITestService>& s);
-bool ConfirmStructuredParcelables(const sp<ITestService>& s);
-bool ConfirmStructuredParcelablesEquality(const sp<ITestService>& s);
-
-}  // namespace client
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
-
-#endif  // ANDROID_AIDL_TESTS_CLIENT_PARCELABLES_H
diff --git a/tests/corpus/enum_named_byte b/tests/corpus/enum_named_byte
new file mode 100644
index 0000000..3cf3ad6
--- /dev/null
+++ b/tests/corpus/enum_named_byte
@@ -0,0 +1 @@
+= import s;enum byte{p}enum s{p} enum oz{p2}parcelable e{e oy;oz y;} 
\ No newline at end of file
diff --git a/tests/corpus/ibinder_array b/tests/corpus/ibinder_array
new file mode 100644
index 0000000..853e41a
--- /dev/null
+++ b/tests/corpus/ibinder_array
@@ -0,0 +1 @@
+ enum F{p}parcelable e{IBinder[]y;}
diff --git a/tests/corpus/nullable_parcelable_array b/tests/corpus/nullable_parcelable_array
new file mode 100644
index 0000000..65cb0af
--- /dev/null
+++ b/tests/corpus/nullable_parcelable_array
@@ -0,0 +1 @@
+)enum r{r}parcelable e{@nullable e[]e;}
\ No newline at end of file
diff --git a/tests/corpus/nullable_pfd_array b/tests/corpus/nullable_pfd_array
new file mode 100644
index 0000000..a18ddd1
--- /dev/null
+++ b/tests/corpus/nullable_pfd_array
@@ -0,0 +1 @@
+ enum F{p}parcelable e{@nullable ParcelFileDescriptor[]y;}
\ No newline at end of file
diff --git a/tests/test_data_example_interface.cpp b/tests/test_data_example_interface.cpp
index c6e0f73..7e23120 100644
--- a/tests/test_data_example_interface.cpp
+++ b/tests/test_data_example_interface.cpp
@@ -548,7 +548,13 @@
     static final int TRANSACTION_takesAnInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
     static final int TRANSACTION_takesAParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
     public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
-      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+      // Only one user of this interface can use this function
+      // at a time. This is a heuristic to detect if two different
+      // users in the same process use this function.
+      if (Stub.Proxy.sDefaultImpl != null) {
+        throw new IllegalStateException("setDefaultImpl() called twice");
+      }
+      if (impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
         return true;
       }
@@ -1062,7 +1068,13 @@
     static final int TRANSACTION_takesAnInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
     static final int TRANSACTION_takesAParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
     public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
-      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+      // Only one user of this interface can use this function
+      // at a time. This is a heuristic to detect if two different
+      // users in the same process use this function.
+      if (Stub.Proxy.sDefaultImpl != null) {
+        throw new IllegalStateException("setDefaultImpl() called twice");
+      }
+      if (impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
         return true;
       }
@@ -1189,165 +1201,157 @@
         }
         case TRANSACTION_isEnabled:
         {
-          data.enforceInterface(descriptor);
-          boolean _result;
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::isEnabled::server");
-            _result = this.isEnabled();
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::isEnabled::server");
+            data.enforceInterface(descriptor);
+            boolean _result = this.isEnabled();
+            reply.writeNoException();
+            reply.writeInt(((_result)?(1):(0)));
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          reply.writeInt(((_result)?(1):(0)));
-          return true;
         }
         case TRANSACTION_getState:
         {
-          data.enforceInterface(descriptor);
-          int _result;
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getState::server");
-            _result = this.getState();
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getState::server");
+            data.enforceInterface(descriptor);
+            int _result = this.getState();
+            reply.writeNoException();
+            reply.writeInt(_result);
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          reply.writeInt(_result);
-          return true;
         }
         case TRANSACTION_getAddress:
         {
-          data.enforceInterface(descriptor);
-          java.lang.String _result;
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getAddress::server");
-            _result = this.getAddress();
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getAddress::server");
+            data.enforceInterface(descriptor);
+            java.lang.String _result = this.getAddress();
+            reply.writeNoException();
+            reply.writeString(_result);
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          reply.writeString(_result);
-          return true;
         }
         case TRANSACTION_getParcelables:
         {
-          data.enforceInterface(descriptor);
-          android.foo.ExampleParcelable[] _result;
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getParcelables::server");
-            _result = this.getParcelables();
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getParcelables::server");
+            data.enforceInterface(descriptor);
+            android.foo.ExampleParcelable[] _result = this.getParcelables();
+            reply.writeNoException();
+            reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-          return true;
         }
         case TRANSACTION_setScanMode:
         {
-          data.enforceInterface(descriptor);
-          int _arg0;
-          _arg0 = data.readInt();
-          int _arg1;
-          _arg1 = data.readInt();
-          boolean _result;
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::setScanMode::server");
-            _result = this.setScanMode(_arg0, _arg1);
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::setScanMode::server");
+            data.enforceInterface(descriptor);
+            int _arg0;
+            _arg0 = data.readInt();
+            int _arg1;
+            _arg1 = data.readInt();
+            boolean _result = this.setScanMode(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeInt(((_result)?(1):(0)));
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          reply.writeInt(((_result)?(1):(0)));
-          return true;
         }
         case TRANSACTION_registerBinder:
         {
-          data.enforceInterface(descriptor);
-          android.bar.IAuxInterface _arg0;
-          _arg0 = android.bar.IAuxInterface.Stub.asInterface(data.readStrongBinder());
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::registerBinder::server");
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::registerBinder::server");
+            data.enforceInterface(descriptor);
+            android.bar.IAuxInterface _arg0;
+            _arg0 = android.bar.IAuxInterface.Stub.asInterface(data.readStrongBinder());
             this.registerBinder(_arg0);
+            reply.writeNoException();
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          return true;
         }
         case TRANSACTION_getRecursiveBinder:
         {
-          data.enforceInterface(descriptor);
-          android.test.IExampleInterface _result;
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getRecursiveBinder::server");
-            _result = this.getRecursiveBinder();
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getRecursiveBinder::server");
+            data.enforceInterface(descriptor);
+            android.test.IExampleInterface _result = this.getRecursiveBinder();
+            reply.writeNoException();
+            reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
-          return true;
         }
         case TRANSACTION_takesAnInterface:
         {
-          data.enforceInterface(descriptor);
-          android.test.IAuxInterface2 _arg0;
-          _arg0 = android.test.IAuxInterface2.Stub.asInterface(data.readStrongBinder());
-          int _result;
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAnInterface::server");
-            _result = this.takesAnInterface(_arg0);
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::takesAnInterface::server");
+            data.enforceInterface(descriptor);
+            android.test.IAuxInterface2 _arg0;
+            _arg0 = android.test.IAuxInterface2.Stub.asInterface(data.readStrongBinder());
+            int _result = this.takesAnInterface(_arg0);
+            reply.writeNoException();
+            reply.writeInt(_result);
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          reply.writeInt(_result);
-          return true;
         }
         case TRANSACTION_takesAParcelable:
         {
-          data.enforceInterface(descriptor);
-          android.test.CompoundParcelable.Subclass1 _arg0;
-          if ((0!=data.readInt())) {
-            _arg0 = android.test.CompoundParcelable.Subclass1.CREATOR.createFromParcel(data);
-          }
-          else {
-            _arg0 = null;
-          }
-          android.test.CompoundParcelable.Subclass2 _arg1;
-          if ((0!=data.readInt())) {
-            _arg1 = android.test.CompoundParcelable.Subclass2.CREATOR.createFromParcel(data);
-          }
-          else {
-            _arg1 = null;
-          }
-          int _result;
           try {
-            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAParcelable::server");
-            _result = this.takesAParcelable(_arg0, _arg1);
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::takesAParcelable::server");
+            data.enforceInterface(descriptor);
+            android.test.CompoundParcelable.Subclass1 _arg0;
+            if ((0!=data.readInt())) {
+              _arg0 = android.test.CompoundParcelable.Subclass1.CREATOR.createFromParcel(data);
+            }
+            else {
+              _arg0 = null;
+            }
+            android.test.CompoundParcelable.Subclass2 _arg1;
+            if ((0!=data.readInt())) {
+              _arg1 = android.test.CompoundParcelable.Subclass2.CREATOR.createFromParcel(data);
+            }
+            else {
+              _arg1 = null;
+            }
+            int _result = this.takesAParcelable(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeInt(_result);
+            if ((_arg1!=null)) {
+              reply.writeInt(1);
+              _arg1.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+            }
+            else {
+              reply.writeInt(0);
+            }
+            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
-          reply.writeNoException();
-          reply.writeInt(_result);
-          if ((_arg1!=null)) {
-            reply.writeInt(1);
-            _arg1.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-          }
-          else {
-            reply.writeInt(0);
-          }
-          return true;
         }
         default:
         {
@@ -1376,7 +1380,7 @@
         android.os.Parcel _reply = android.os.Parcel.obtain();
         boolean _result;
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::isEnabled::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::isEnabled::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_isEnabled, _data, _reply, 0);
           if (!_status && getDefaultImpl() != null) {
@@ -1398,7 +1402,7 @@
         android.os.Parcel _reply = android.os.Parcel.obtain();
         int _result;
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getState::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getState::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_getState, _data, _reply, 0);
           if (!_status && getDefaultImpl() != null) {
@@ -1420,7 +1424,7 @@
         android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String _result;
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getAddress::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getAddress::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_getAddress, _data, _reply, 0);
           if (!_status && getDefaultImpl() != null) {
@@ -1443,7 +1447,7 @@
         android.os.Parcel _reply = android.os.Parcel.obtain();
         android.foo.ExampleParcelable[] _result;
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getParcelables::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getParcelables::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_getParcelables, _data, _reply, 0);
           if (!_status && getDefaultImpl() != null) {
@@ -1467,7 +1471,7 @@
         android.os.Parcel _reply = android.os.Parcel.obtain();
         boolean _result;
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::setScanMode::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::setScanMode::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           _data.writeInt(mode);
           _data.writeInt(duration);
@@ -1492,7 +1496,7 @@
         android.os.Parcel _data = android.os.Parcel.obtain();
         android.os.Parcel _reply = android.os.Parcel.obtain();
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::registerBinder::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::registerBinder::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           _data.writeStrongBinder((((foo!=null))?(foo.asBinder()):(null)));
           boolean _status = mRemote.transact(Stub.TRANSACTION_registerBinder, _data, _reply, 0);
@@ -1514,7 +1518,7 @@
         android.os.Parcel _reply = android.os.Parcel.obtain();
         android.test.IExampleInterface _result;
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getRecursiveBinder::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getRecursiveBinder::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_getRecursiveBinder, _data, _reply, 0);
           if (!_status && getDefaultImpl() != null) {
@@ -1536,7 +1540,7 @@
         android.os.Parcel _reply = android.os.Parcel.obtain();
         int _result;
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAnInterface::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::takesAnInterface::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           _data.writeStrongBinder((((arg!=null))?(arg.asBinder()):(null)));
           boolean _status = mRemote.transact(Stub.TRANSACTION_takesAnInterface, _data, _reply, 0);
@@ -1559,7 +1563,7 @@
         android.os.Parcel _reply = android.os.Parcel.obtain();
         int _result;
         try {
-          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAParcelable::client");
+          android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::takesAParcelable::client");
           _data.writeInterfaceToken(DESCRIPTOR);
           if ((arg!=null)) {
             _data.writeInt(1);
@@ -1604,7 +1608,13 @@
     static final int TRANSACTION_takesAnInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
     static final int TRANSACTION_takesAParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
     public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
-      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+      // Only one user of this interface can use this function
+      // at a time. This is a heuristic to detect if two different
+      // users in the same process use this function.
+      if (Stub.Proxy.sDefaultImpl != null) {
+        throw new IllegalStateException("setDefaultImpl() called twice");
+      }
+      if (impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
         return true;
       }
@@ -2094,7 +2104,13 @@
       return true;
     }
     public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
-      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+      // Only one user of this interface can use this function
+      // at a time. This is a heuristic to detect if two different
+      // users in the same process use this function.
+      if (Stub.Proxy.sDefaultImpl != null) {
+        throw new IllegalStateException("setDefaultImpl() called twice");
+      }
+      if (impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
         return true;
       }
@@ -2546,7 +2562,7 @@
       }
       @Override
       public synchronized String getInterfaceHash() throws android.os.RemoteException {
-        if (mCachedHash == "-1") {
+        if ("-1".equals(mCachedHash)) {
           android.os.Parcel data = android.os.Parcel.obtain();
           android.os.Parcel reply = android.os.Parcel.obtain();
           try {
@@ -2660,7 +2676,13 @@
     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) {
+      // Only one user of this interface can use this function
+      // at a time. This is a heuristic to detect if two different
+      // users in the same process use this function.
+      if (Stub.Proxy.sDefaultImpl != null) {
+        throw new IllegalStateException("setDefaultImpl() called twice");
+      }
+      if (impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
         return true;
       }
diff --git a/tests/test_data_string_constants.cpp b/tests/test_data_string_constants.cpp
index 8b1b479..2bbd8fd 100644
--- a/tests/test_data_string_constants.cpp
+++ b/tests/test_data_string_constants.cpp
@@ -107,7 +107,13 @@
       public static android.os.IStringConstants sDefaultImpl;
     }
     public static boolean setDefaultImpl(android.os.IStringConstants impl) {
-      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+      // Only one user of this interface can use this function
+      // at a time. This is a heuristic to detect if two different
+      // users in the same process use this function.
+      if (Stub.Proxy.sDefaultImpl != null) {
+        throw new IllegalStateException("setDefaultImpl() called twice");
+      }
+      if (impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
         return true;
       }
@@ -354,7 +360,7 @@
       }
       @Override
       public synchronized String getInterfaceHash() throws android.os.RemoteException {
-        if (mCachedHash == "-1") {
+        if ("-1".equals(mCachedHash)) {
           android.os.Parcel data = android.os.Parcel.obtain();
           android.os.Parcel reply = android.os.Parcel.obtain();
           try {
@@ -379,7 +385,13 @@
     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) {
+      // Only one user of this interface can use this function
+      // at a time. This is a heuristic to detect if two different
+      // users in the same process use this function.
+      if (Stub.Proxy.sDefaultImpl != null) {
+        throw new IllegalStateException("setDefaultImpl() called twice");
+      }
+      if (impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
         return true;
       }
diff --git a/trace/android/trace.h b/trace/android/trace.h
new file mode 100644
index 0000000..cd6294c
--- /dev/null
+++ b/trace/android/trace.h
@@ -0,0 +1,26 @@
+/*
+ * 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 <cutils/trace.h>
+
+inline void ATrace_beginSection(const char* sectionName) {
+  atrace_begin(ATRACE_TAG_AIDL, sectionName);
+}
+
+inline void ATrace_endSection() {
+  atrace_end(ATRACE_TAG_AIDL);
+}