hidl2aidl: support nested type definitions in AIDL

Previously all types needed seperate AIDL files. Now, AIDL supports
nesting definitions within other types and interfaces.
If a type was nested in HIDL, it is now nested in the generated AIDL.

Test: atest hidl2aidl_translate_ndk_test hidl2aidl_translate_java_test
hidl2aidl_translate_cpp_test
Test: ./run_build_file_test.sh
Bug: 201792373

Change-Id: Iaf0933b87f40a4b2540fda707276ee8fae6985b0
diff --git a/hidl2aidl/AidlHelper.cpp b/hidl2aidl/AidlHelper.cpp
index f1c4dfe..27d80f7 100644
--- a/hidl2aidl/AidlHelper.cpp
+++ b/hidl2aidl/AidlHelper.cpp
@@ -51,12 +51,23 @@
     notesFormatter = formatter;
 }
 
-std::string AidlHelper::getAidlName(const FQName& fqName) {
+std::string AidlHelper::getAidlName(const FQName& fqName, AidlBackend backend) {
     std::vector<std::string> names;
     for (const std::string& name : fqName.names()) {
         names.push_back(StringHelper::Capitalize(name));
     }
-    return StringHelper::JoinStrings(names, "");
+    switch (backend) {
+        case AidlBackend::CPP:
+            /* fall through */
+        case AidlBackend::NDK:
+            return StringHelper::JoinStrings(names, "::");
+        case AidlBackend::JAVA:
+            return StringHelper::JoinStrings(names, ".");
+        case AidlBackend::UNKNOWN:
+            /* fall through */
+        default:
+            return StringHelper::Capitalize(names.back());
+    }
 }
 
 std::string AidlHelper::getAidlPackage(const FQName& fqName) {
@@ -80,18 +91,42 @@
     return getAidlPackage(fqName) + "." + getAidlName(fqName);
 }
 
-void AidlHelper::importLocallyReferencedType(const Type& type, std::set<FQName>* imports) {
+const NamedType* AidlHelper::getTopLevelType(const NamedType* type) {
+    if (type->parent() && type->parent()->fqName().hasVersion()) {
+        auto base_type = type->parent();
+        while (base_type->parent() && base_type->parent()->fqName().hasVersion()) {
+            base_type = base_type->parent();
+        }
+        return base_type;
+    } else {
+        return type;
+    }
+}
+
+static void importLocallyReferencedType(const Type& scope, const Type& type,
+                                        std::set<FQName>* imports) {
     if (type.isArray()) {
-        return importLocallyReferencedType(*static_cast<const ArrayType*>(&type)->getElementType(),
-                                           imports);
+        return importLocallyReferencedType(
+                scope, *static_cast<const ArrayType*>(&type)->getElementType(), imports);
     }
     if (type.isTemplatedType()) {
         return importLocallyReferencedType(
-                *static_cast<const TemplatedType*>(&type)->getElementType(), imports);
+                scope, *static_cast<const TemplatedType*>(&type)->getElementType(), imports);
     }
 
     if (!type.isNamedType()) return;
     const NamedType& namedType = *static_cast<const NamedType*>(&type);
+    // If this type has the same top level type as the scope, then it is defined
+    // in the same file and does not need to be imported.
+    if (scope.isNamedType()) {
+        const auto& scopeTopLevel =
+                AidlHelper::getTopLevelType(static_cast<const NamedType*>(&scope));
+        const auto& thisTopLevel = AidlHelper::getTopLevelType(&namedType);
+        // The fqName might not be equal because of differing HIDL versions for the
+        // top level type. Generated AIDL does not have these differences in
+        // versions, so we can test the equality of the name.
+        if (scopeTopLevel->fqName().name() == thisTopLevel->fqName().name()) return;
+    }
     imports->insert(namedType.fqName());
 }
 
@@ -107,14 +142,6 @@
 
     std::set<FQName> imports;
 
-    // Import all the defined types since they will now be in a different file
-    if (type.isScope()) {
-        const Scope& scope = static_cast<const Scope&>(type);
-        for (const NamedType* namedType : scope.getSubTypes()) {
-            importLocallyReferencedType(*namedType, &imports);
-        }
-    }
-
     // Import all the referenced types
     if (type.isInterface()) {
         // This is a separate case because getReferences doesn't traverse all the superTypes and
@@ -123,7 +150,7 @@
                 getUserDefinedMethods(out, static_cast<const Interface&>(type));
         for (const Method* method : methods) {
             for (const Reference<Type>* ref : method->getReferences()) {
-                importLocallyReferencedType(*ref->get(), &imports);
+                importLocallyReferencedType(type, *ref->get(), &imports);
             }
         }
     } else if (type.isCompoundType()) {
@@ -134,10 +161,7 @@
         const ProcessedCompoundType& processedType = it->second;
 
         for (const auto& field : processedType.fields) {
-            importLocallyReferencedType(*field.field->get(), &imports);
-        }
-        for (const auto& subType : processedType.subTypes) {
-            importLocallyReferencedType(*subType, &imports);
+            importLocallyReferencedType(type, *field.field->get(), &imports);
         }
     } else {
         for (const Reference<Type>* ref : type.getReferences()) {
@@ -145,7 +169,7 @@
                 // Don't import the referenced type if this is referencing itself
                 continue;
             }
-            importLocallyReferencedType(*ref->get(), &imports);
+            importLocallyReferencedType(type, *ref->get(), &imports);
         }
     }
 
diff --git a/hidl2aidl/AidlHelper.h b/hidl2aidl/AidlHelper.h
index c924176..94a1efc 100644
--- a/hidl2aidl/AidlHelper.h
+++ b/hidl2aidl/AidlHelper.h
@@ -63,8 +63,14 @@
 struct AidlHelper {
     /* FQName helpers */
     // getAidlName returns the type names
-    // android.hardware.foo@1.0::IBar.Baz -> IBarBaz
-    static std::string getAidlName(const FQName& fqName);
+    // backend == UNKNOWN
+    // android.hardware.foo@1.0::IBar::Baz -> Baz
+    // backend == CPP || backend == NDK
+    // android.hardware.foo@1.0::IBar::Baz -> IBar::Baz
+    // backend == JAVA
+    // android.hardware.foo@1.0::IBar::Baz -> IBar.Baz
+    static std::string getAidlName(const FQName& fqName,
+                                   AidlBackend backend = AidlBackend::UNKNOWN);
 
     // getAidlPackage returns the AIDL package
     // android.hardware.foo@1.x -> android.hardware.foo
@@ -83,21 +89,24 @@
     static void emitFileHeader(
             Formatter& out, const NamedType& type,
             const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes);
-    static void importLocallyReferencedType(const Type& type, std::set<FQName>* imports);
     static Formatter getFileWithHeader(
             const NamedType& namedType, const Coordinator& coordinator,
             const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes);
 
     /* Methods for Type */
-    static std::string getAidlType(const Type& type, const FQName& relativeTo);
+    static std::string getAidlType(const Type& type, const FQName& relativeTo,
+                                   AidlBackend backend = AidlBackend::UNKNOWN);
 
     /* Methods for NamedType */
     static void emitAidl(
-            const NamedType& namedType, const Coordinator& coordinator,
+            const NamedType& namedType, Formatter& out,
             const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes);
 
+    // Walk through all of the type's parents until we reach the top and return.
+    static const NamedType* getTopLevelType(const NamedType* type);
+
     /* Methods for Interface */
-    static void emitAidl(const Interface& interface, const Coordinator& coordinator,
+    static void emitAidl(const Interface& interface, Formatter& out,
                          const std::map<const NamedType*, const ProcessedCompoundType>&);
     // Returns all methods that would exist in an AIDL equivalent interface
     static std::vector<const Method*> getUserDefinedMethods(Formatter& out,
diff --git a/hidl2aidl/AidlInterface.cpp b/hidl2aidl/AidlInterface.cpp
index d8136de..5fb56ca 100644
--- a/hidl2aidl/AidlInterface.cpp
+++ b/hidl2aidl/AidlInterface.cpp
@@ -171,10 +171,8 @@
 }
 
 void AidlHelper::emitAidl(
-        const Interface& interface, const Coordinator& coordinator,
+        const Interface& interface, Formatter& out,
         const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes) {
-    Formatter out = getFileWithHeader(interface, coordinator, processedTypes);
-
     interface.emitDocComment(out);
     if (interface.superType() && interface.superType()->fqName() != gIBaseFqName) {
         out << "// Interface inherits from " << interface.superType()->fqName().string()
@@ -225,7 +223,10 @@
                          << " since a newer alternative is available.";
                  });
         if (!supersededNamedTypes.empty()) out << "\n\n";
-
+        // Emit the nested type definitions
+        for (const auto& [name, type] : latestTypeForBaseName) {
+            emitAidl(*type.node, out, processedTypes);
+        }
         // Add comment for superseded methods
         out.join(supersededMethods.begin(), supersededMethods.end(), "\n",
                  [&](const NodeWithVersion<Method>& versionedMethod) {
diff --git a/hidl2aidl/AidlNamedType.cpp b/hidl2aidl/AidlNamedType.cpp
index 026331d..bf308a5 100644
--- a/hidl2aidl/AidlNamedType.cpp
+++ b/hidl2aidl/AidlNamedType.cpp
@@ -94,6 +94,10 @@
         out << "union " << AidlHelper::getAidlName(compoundType.fqName()) << " ";
     }
     out.block([&] {
+        // Emit all nested type definitions
+        for (auto const& type : processedType.subTypes) {
+            AidlHelper::emitAidl(*type, out, processedTypes);
+        }
         // Emit all of the fields from the processed type
         for (auto const& fieldWithVersion : processedType.fields) {
             fieldWithVersion.field->emitDocComment(out);
@@ -105,11 +109,9 @@
     out << "\n";
 }
 
-// TODO: Enum/Typedef should just emit to hidl-error.log or similar
 void AidlHelper::emitAidl(
-        const NamedType& namedType, const Coordinator& coordinator,
+        const NamedType& namedType, Formatter& out,
         const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes) {
-    Formatter out = getFileWithHeader(namedType, coordinator, processedTypes);
     if (namedType.isTypeDef()) {
         const TypeDef& typeDef = static_cast<const TypeDef&>(namedType);
         emitTypeDefAidlDefinition(out, typeDef);
@@ -121,7 +123,7 @@
         emitEnumAidlDefinition(out, enumType);
     } else if (namedType.isInterface()) {
         const Interface& iface = static_cast<const Interface&>(namedType);
-        emitAidl(iface, coordinator, processedTypes);
+        emitAidl(iface, out, processedTypes);
     } else {
         out << "// TODO: Fix this " << namedType.definedName() << "\n";
     }
diff --git a/hidl2aidl/AidlTranslate.cpp b/hidl2aidl/AidlTranslate.cpp
index 6dbee90..4ee7f00 100644
--- a/hidl2aidl/AidlTranslate.cpp
+++ b/hidl2aidl/AidlTranslate.cpp
@@ -69,7 +69,7 @@
     const std::string separator = (backend == AidlBackend::JAVA) ? "." : "::";
     return prefix +
            base::Join(base::Split(AidlHelper::getAidlPackage(type.fqName()), "."), separator) +
-           separator + AidlHelper::getAidlType(type, type.fqName());
+           separator + AidlHelper::getAidlType(type, type.fqName(), backend);
 }
 
 static void emitEnumStaticAssert(Formatter& out, const NamedType& namedType, AidlBackend backend) {
@@ -439,7 +439,7 @@
         if (it == processedTypes.end() && !type->isEnum()) {
             continue;
         }
-        includes.insert(aidlIncludeFile(type, backend));
+        includes.insert(aidlIncludeFile(AidlHelper::getTopLevelType(type), backend));
         includes.insert(hidlIncludeFile(type));
     }
     out << base::Join(includes, "") << "\n\n";
diff --git a/hidl2aidl/AidlType.cpp b/hidl2aidl/AidlType.cpp
index 471044e..7ba9d21 100644
--- a/hidl2aidl/AidlType.cpp
+++ b/hidl2aidl/AidlType.cpp
@@ -46,7 +46,8 @@
     return std::nullopt;
 }
 
-std::string AidlHelper::getAidlType(const Type& type, const FQName& relativeTo) {
+std::string AidlHelper::getAidlType(const Type& type, const FQName& relativeTo,
+                                    AidlBackend backend) {
     if (type.isVector()) {
         const VectorType& vec = static_cast<const VectorType&>(type);
         return getAidlType(*vec.getElementType(), relativeTo) + "[]";
@@ -56,7 +57,7 @@
     } else if (type.isNamedType()) {
         const NamedType& namedType = static_cast<const NamedType&>(type);
         if (getAidlPackage(relativeTo) == getAidlPackage(namedType.fqName())) {
-            return getAidlName(namedType.fqName());
+            return getAidlName(namedType.fqName(), backend);
         } else {
             std::optional<const ReplacedTypeInfo> type = getAidlReplacedType(namedType.fqName());
             if (type) {
diff --git a/hidl2aidl/main.cpp b/hidl2aidl/main.cpp
index b6348ee..5d48860 100644
--- a/hidl2aidl/main.cpp
+++ b/hidl2aidl/main.cpp
@@ -372,7 +372,7 @@
         }
     }
 
-    // This is the list of all types which should be converted
+    // This is the list of all targets which should be converted
     std::vector<FQName> targets;
     for (FQName version = getLowestExistingFqName(coordinator, fqName);
          version.getPackageMinorVersion() <= fqName.getPackageMinorVersion();
@@ -459,7 +459,11 @@
     // emitAidl. The interfaces are consolidating methods from their typechains
     // and the composite types are being flattened.
     for (const auto& namedType : namedTypesInPackage) {
-        AidlHelper::emitAidl(*namedType, coordinator, processedTypesInPackage);
+        // Nested types do not get their own files
+        if (namedType->fqName().names().size() > 1) continue;
+        Formatter out =
+                AidlHelper::getFileWithHeader(*namedType, coordinator, processedTypesInPackage);
+        AidlHelper::emitAidl(*namedType, out, processedTypesInPackage);
     }
 
     err << "END OF LOG\n";
diff --git a/hidl2aidl/test/Android.bp b/hidl2aidl/test/Android.bp
index e12c9fe..203fbb6 100644
--- a/hidl2aidl/test/Android.bp
+++ b/hidl2aidl/test/Android.bp
@@ -60,17 +60,13 @@
         "hidl2aidl/test/VectorFoo.aidl",
         "hidl2aidl/test/FooFlag.aidl",
         "hidl2aidl/test/IBar.aidl",
-        "hidl2aidl/test/IBarInner.aidl",
         "hidl2aidl/test/IFoo.aidl",
-        "hidl2aidl/test/IFooBigStruct.aidl",
         "hidl2aidl/test/NameCollision.aidl",
         "hidl2aidl/test/OnlyIn10.aidl",
         "hidl2aidl/test/OnlyIn11.aidl",
         "hidl2aidl/test/Outer.aidl",
-        "hidl2aidl/test/OuterInner.aidl",
         "hidl2aidl/test/OverrideMe.aidl",
         "hidl2aidl/test/SafeUnionBar.aidl",
-        "hidl2aidl/test/SafeUnionBarInnerStructBar.aidl",
         "hidl2aidl/test/UnionFoo.aidl",
         "hidl2aidl/test/Value.aidl",
         "hidl2aidl/test2/IFoo.aidl",
diff --git a/hidl2aidl/test/TranslateJavaTest.java b/hidl2aidl/test/TranslateJavaTest.java
index aabbeed..d32262d 100644
--- a/hidl2aidl/test/TranslateJavaTest.java
+++ b/hidl2aidl/test/TranslateJavaTest.java
@@ -65,7 +65,7 @@
 
     @Test
     public void OuterInner() {
-        hidl2aidl.test.OuterInner dest;
+        hidl2aidl.test.Outer.Inner dest;
         hidl2aidl.test.V1_0.Outer.Inner source = new hidl2aidl.test.V1_0.Outer.Inner();
         source.a = 12;
         dest = Translate.h2aTranslate(source);
@@ -87,7 +87,7 @@
 
     @Test
     public void IFooBigStruct() {
-        hidl2aidl.test.IFooBigStruct dest;
+        hidl2aidl.test.IFoo.BigStruct dest;
         hidl2aidl.test.V1_1.IFoo.BigStruct source = new hidl2aidl.test.V1_1.IFoo.BigStruct();
         source.type = 12;
         source.value = 16;
@@ -98,7 +98,7 @@
 
     @Test
     public void IBarInner() {
-        hidl2aidl.test.IBarInner dest;
+        hidl2aidl.test.IBar.Inner dest;
         hidl2aidl.test.V1_0.IBar.Inner source = new hidl2aidl.test.V1_0.IBar.Inner();
         source.a = 0x70000000;
         dest = Translate.h2aTranslate(source);
@@ -107,7 +107,7 @@
 
     @Test
     public void UnsignedToSignedTooLarge() {
-        hidl2aidl.test.IBarInner dest;
+        hidl2aidl.test.IBar.Inner dest;
         hidl2aidl.test.V1_0.IBar.Inner source = new hidl2aidl.test.V1_0.IBar.Inner();
         // source.a is uint32_t, dest.a is int32_t
         source.a = -1;
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IBar.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IBar.aidl
index cbd8a37..405b46e 100644
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IBar.aidl
+++ b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IBar.aidl
@@ -20,7 +20,11 @@
 package hidl2aidl.test;
 @VintfStability
 interface IBar {
-  void extraMethod(in hidl2aidl.test.IBarInner inner);
+  void extraMethod(in hidl2aidl.test.IBar.Inner inner);
   String someBar(in String a, in byte b);
   oneway void someFoo(in byte a);
+  @VintfStability
+  parcelable Inner {
+    int a;
+  }
 }
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IBarInner.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IBarInner.aidl
deleted file mode 100644
index 78c9d3b..0000000
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IBarInner.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-// FIXME: license file, or use the -l option to generate the files with the header.
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package hidl2aidl.test;
-@VintfStability
-parcelable IBarInner {
-  int a;
-}
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IFoo.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IFoo.aidl
index b990a90..8c6bc29 100644
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IFoo.aidl
+++ b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IFoo.aidl
@@ -21,14 +21,19 @@
 @VintfStability
 interface IFoo {
   void multipleInputs(in String in1, in String in2);
-  void multipleInputsAndOutputs(in String in1, in String in2, out hidl2aidl.test.IFooBigStruct out1, out hidl2aidl.test.IFooBigStruct out2);
-  void multipleOutputs(out hidl2aidl.test.IFooBigStruct out1, out hidl2aidl.test.IFooBigStruct out2);
+  void multipleInputsAndOutputs(in String in1, in String in2, out hidl2aidl.test.IFoo.BigStruct out1, out hidl2aidl.test.IFoo.BigStruct out2);
+  void multipleOutputs(out hidl2aidl.test.IFoo.BigStruct out1, out hidl2aidl.test.IFoo.BigStruct out2);
   String oneOutput();
   String removedOutput();
   void someBar(in String a, in String b);
   oneway void someFoo(in byte a);
   void useImportedStruct(in hidl2aidl.test.Outer outer);
-  hidl2aidl.test.IFooBigStruct useStruct();
+  hidl2aidl.test.IFoo.BigStruct useStruct();
   void versionTest_(in String a);
   boolean versionTest_two_(in String a);
+  @VintfStability
+  parcelable BigStruct {
+    byte type;
+    byte value;
+  }
 }
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IFooBigStruct.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IFooBigStruct.aidl
deleted file mode 100644
index 81a292a..0000000
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/IFooBigStruct.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-// FIXME: license file, or use the -l option to generate the files with the header.
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package hidl2aidl.test;
-@VintfStability
-parcelable IFooBigStruct {
-  byte type;
-  byte value;
-}
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/Outer.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/Outer.aidl
index a3e3eb7..e5ea413 100644
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/Outer.aidl
+++ b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/Outer.aidl
@@ -20,6 +20,10 @@
 package hidl2aidl.test;
 @VintfStability
 parcelable Outer {
-  hidl2aidl.test.OuterInner inner;
+  hidl2aidl.test.Outer.Inner inner;
   int a;
+  @VintfStability
+  parcelable Inner {
+    byte a;
+  }
 }
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/OuterInner.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/OuterInner.aidl
deleted file mode 100644
index e23b9df..0000000
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/OuterInner.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-// FIXME: license file, or use the -l option to generate the files with the header.
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package hidl2aidl.test;
-@VintfStability
-parcelable OuterInner {
-  byte a;
-}
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBar.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBar.aidl
index 89d3703..b49a082 100644
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBar.aidl
+++ b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBar.aidl
@@ -23,7 +23,7 @@
   boolean noInit;
   byte a;
   long b;
-  hidl2aidl.test.SafeUnionBarInnerStructBar innerStructBar;
+  hidl2aidl.test.SafeUnionBar.InnerStructBar innerStructBar;
   hidl2aidl.test.OnlyIn11 c;
   String d;
   float e;
@@ -35,4 +35,9 @@
   hidl2aidl.test.Value[] k;
   byte[] l;
   float m;
+  @VintfStability
+  parcelable InnerStructBar {
+    byte x;
+    byte z;
+  }
 }
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBarInnerStructBar.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBarInnerStructBar.aidl
deleted file mode 100644
index 3fd291f..0000000
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBarInnerStructBar.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-// FIXME: license file, or use the -l option to generate the files with the header.
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package hidl2aidl.test;
-@VintfStability
-parcelable SafeUnionBarInnerStructBar {
-  byte x;
-  byte z;
-}
diff --git a/hidl2aidl/test/cpp_test_compile.cpp b/hidl2aidl/test/cpp_test_compile.cpp
index 56ad7ce..16a7ab0 100644
--- a/hidl2aidl/test/cpp_test_compile.cpp
+++ b/hidl2aidl/test/cpp_test_compile.cpp
@@ -22,14 +22,11 @@
 #include <hidl2aidl/test/BpBar.h>
 #include <hidl2aidl/test/BpFoo.h>
 #include <hidl2aidl/test/IBar.h>
-#include <hidl2aidl/test/IBarInner.h>
 #include <hidl2aidl/test/IFoo.h>
-#include <hidl2aidl/test/IFooBigStruct.h>
 #include <hidl2aidl/test/NameCollision.h>
 #include <hidl2aidl/test/OnlyIn10.h>
 #include <hidl2aidl/test/OnlyIn11.h>
 #include <hidl2aidl/test/Outer.h>
-#include <hidl2aidl/test/OuterInner.h>
 #include <hidl2aidl/test/OverrideMe.h>
 #include <hidl2aidl/test/Value.h>
 #include <hidl2aidl/test2/BnFoo.h>
@@ -46,7 +43,7 @@
     String16 f;
     Status status2 = foo->oneOutput(&f);
     (void)status2;
-    hidl2aidl::test::IFooBigStruct big_struct;
+    hidl2aidl::test::IFoo::BigStruct big_struct;
     big_struct.type = 2;
     big_struct.value = 3;
     // Test some of the types here as well
@@ -65,7 +62,7 @@
     String16 out;
     Status status1 = bar->someBar(String16(), 3, &out);
     (void)status1;
-    hidl2aidl::test::IBarInner inner;
+    hidl2aidl::test::IBar::Inner inner;
     inner.a = 3;
     Status status2 = bar->extraMethod(inner);
     (void)status2;
diff --git a/hidl2aidl/test/ndk_test_compile.cpp b/hidl2aidl/test/ndk_test_compile.cpp
index 5b427c5..ebfd414 100644
--- a/hidl2aidl/test/ndk_test_compile.cpp
+++ b/hidl2aidl/test/ndk_test_compile.cpp
@@ -22,13 +22,10 @@
 #include <aidl/hidl2aidl/test/BpBar.h>
 #include <aidl/hidl2aidl/test/BpFoo.h>
 #include <aidl/hidl2aidl/test/IBar.h>
-#include <aidl/hidl2aidl/test/IBarInner.h>
 #include <aidl/hidl2aidl/test/IFoo.h>
-#include <aidl/hidl2aidl/test/IFooBigStruct.h>
 #include <aidl/hidl2aidl/test/OnlyIn10.h>
 #include <aidl/hidl2aidl/test/OnlyIn11.h>
 #include <aidl/hidl2aidl/test/Outer.h>
-#include <aidl/hidl2aidl/test/OuterInner.h>
 #include <aidl/hidl2aidl/test/OverrideMe.h>
 #include <aidl/hidl2aidl/test/Value.h>
 #include <aidl/hidl2aidl/test2/BnFoo.h>
@@ -47,7 +44,7 @@
     std::string out;
     ndk::ScopedAStatus status1 = bar->someBar(std::string(), 3, &out);
     (void)status1;
-    aidl::hidl2aidl::test::IBarInner inner;
+    aidl::hidl2aidl::test::IBar::Inner inner;
     inner.a = 3;
     ndk::ScopedAStatus status2 = bar->extraMethod(inner);
     (void)status2;
diff --git a/hidl2aidl/test/translate_cpp_test.cpp b/hidl2aidl/test/translate_cpp_test.cpp
index b3a5161..6ba4e09 100644
--- a/hidl2aidl/test/translate_cpp_test.cpp
+++ b/hidl2aidl/test/translate_cpp_test.cpp
@@ -58,7 +58,7 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, OuterInner) {
-    hidl2aidl::test::OuterInner dest;
+    hidl2aidl::test::Outer::Inner dest;
     hidl2aidl::test::V1_0::Outer::Inner source;
     source.a = 12;
     ASSERT_TRUE(h2a::translate(source, &dest));
@@ -78,7 +78,7 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, IFooBigStruct) {
-    hidl2aidl::test::IFooBigStruct dest;
+    hidl2aidl::test::IFoo::BigStruct dest;
     hidl2aidl::test::V1_1::IFoo::BigStruct source;
     source.type = 12;
     source.value = 16;
@@ -88,7 +88,7 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, IBarInner) {
-    hidl2aidl::test::IBarInner dest;
+    hidl2aidl::test::IBar::Inner dest;
     hidl2aidl::test::V1_0::IBar::Inner source;
     source.a = 0x70000000;
     ASSERT_TRUE(h2a::translate(source, &dest));
@@ -96,7 +96,7 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, UnsignedToSignedTooLarge) {
-    hidl2aidl::test::IBarInner dest;
+    hidl2aidl::test::IBar::Inner dest;
     hidl2aidl::test::V1_0::IBar::Inner source;
     // source.a is uint32_t, dest.a is int32_t
     source.a = 0xf0000000;
diff --git a/hidl2aidl/test/translate_ndk_test.cpp b/hidl2aidl/test/translate_ndk_test.cpp
index 20a9ee7..5913a01 100644
--- a/hidl2aidl/test/translate_ndk_test.cpp
+++ b/hidl2aidl/test/translate_ndk_test.cpp
@@ -58,7 +58,7 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, OuterInner) {
-    aidl::hidl2aidl::test::OuterInner dest;
+    aidl::hidl2aidl::test::Outer::Inner dest;
     hidl2aidl::test::V1_0::Outer::Inner source;
     source.a = 12;
     ASSERT_TRUE(h2a::translate(source, &dest));
@@ -78,7 +78,7 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, IFooBigStruct) {
-    aidl::hidl2aidl::test::IFooBigStruct dest;
+    aidl::hidl2aidl::test::IFoo::BigStruct dest;
     hidl2aidl::test::V1_1::IFoo::BigStruct source;
     source.type = 12;
     source.value = 16;
@@ -88,7 +88,7 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, IBarInner) {
-    aidl::hidl2aidl::test::IBarInner dest;
+    aidl::hidl2aidl::test::IBar::Inner dest;
     hidl2aidl::test::V1_0::IBar::Inner source;
     source.a = 0x70000000;
     ASSERT_TRUE(h2a::translate(source, &dest));
@@ -96,7 +96,7 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, UnsignedToSignedTooLarge) {
-    aidl::hidl2aidl::test::IBarInner dest;
+    aidl::hidl2aidl::test::IBar::Inner dest;
     hidl2aidl::test::V1_0::IBar::Inner source;
     // source.a is uint32_t, dest.a is int32_t
     source.a = 0xf0000000;