IHidlInterfaceBase for all autogenerated interfaces.

Add an interfaceChain() method to each interface
to facilitate casting between interfaces.

Add ::descriptor for each interface (so that
IFoo::descriptor won't fall back to
IHidlInterfaceBase::descriptor.

Test: hidl_test
Test: cd system/tools/hidl && mma
Test: cd hardware/interfaces/test && mma

Bug: 32337854
Change-Id: I317b7905750db0bfefc4c5fd608a07080923c719
diff --git a/Interface.cpp b/Interface.cpp
index 5951f87..09959ae 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -18,51 +18,119 @@
 
 #include "Annotation.h"
 #include "Method.h"
+#include "StringType.h"
+#include "VectorType.h"
 
 #include <android-base/logging.h>
 #include <hidl-util/Formatter.h>
+#include <hidl-util/StringHelper.h>
 #include <iostream>
+#include <sstream>
 
 namespace android {
 
+/* It is very important that these values NEVER change. These values
+ * must remain unchanged over the lifetime of android. This is
+ * because the framework on a device will be updated independently of
+ * the hals on a device. If the hals are compiled with one set of
+ * transaction values, and the framework with another, then the
+ * interface between them will be destroyed, and the device will not
+ * work.
+ */
+enum {
+    // These values are defined in hardware::IBinder.
+    /////////////////// User defined transactions
+    FIRST_CALL_TRANSACTION  = 0x00000001,
+    LAST_CALL_TRANSACTION   = 0x00efffff,
+    /////////////////// HIDL reserved
+    FIRST_HIDL_TRANSACTION  = 0x00f00000,
+    HIDL_DESCRIPTOR_CHAIN_TRANSACTION = FIRST_HIDL_TRANSACTION,
+    LAST_HIDL_TRANSACTION   = 0x00ffffff,
+};
+
 Interface::Interface(const char *localName, Interface *super)
     : Scope(localName),
       mSuperType(super),
       mIsJavaCompatibleInProgress(false) {
+    mReservedMethods.push_back(createDescriptorChainMethod());
 }
 
+Method *Interface::createDescriptorChainMethod() const {
+    VectorType *vecType = new VectorType();
+    vecType->setElementType(new StringType());
+    std::vector<TypedVar *> *results = new std::vector<TypedVar *>();
+    results->push_back(new TypedVar("indicator", vecType));
+
+    return new Method("interfaceChain",
+        new std::vector<TypedVar *>() /* args */,
+        results,
+        false /* oneway */,
+        new std::vector<Annotation *>(),
+        HIDL_DESCRIPTOR_CHAIN_TRANSACTION,
+        [this](auto &out) { /* cppImpl */
+            std::vector<const Interface *> chain = typeChain();
+            out << "::android::hardware::hidl_vec<::android::hardware::hidl_string> _hidl_return;\n";
+            out << "_hidl_return.resize(" << chain.size() << ");\n";
+            for (size_t i = 0; i < chain.size(); ++i) {
+                out << "_hidl_return[" << i << "] = \"" << chain[i]->fqName().string() << "\";\n";
+            }
+            out << "_hidl_cb(_hidl_return);\n";
+            out << "return ::android::hardware::Void();";
+        },
+        [this](auto &out) { /* javaImpl */
+            std::vector<const Interface *> chain = typeChain();
+            out << "return new ArrayList<String>(Arrays.asList(\n";
+            out.indent(); out.indent();
+            for (size_t i = 0; i < chain.size(); ++i) {
+                if (i != 0)
+                    out << ",\n";
+                out << "\"" << chain[i]->fqName().string() << "\"";
+            }
+            out << "));";
+            out.unindent(); out.unindent();
+        });
+}
+
+
 bool Interface::addMethod(Method *method) {
+    CHECK(!method->isHidlReserved());
     if (lookupMethod(method->name()) != nullptr) {
         LOG(ERROR) << "Redefinition of method " << method->name();
         return false;
     }
+    size_t serial = FIRST_CALL_TRANSACTION;
 
-    /* It is very important that these values NEVER change. These values
-     * must remain unchanged over the lifetime of android. This is
-     * because the framework on a device will be updated independently of
-     * the hals on a device. If the hals are compiled with one set of
-     * transaction values, and the framework with another, then the
-     * interface between them will be destroyed, and the device will not
-     * work.
-     */
-    size_t serial = 1; // hardware::IBinder::FIRST_CALL_TRANSACTION;
+    serial += userDefinedMethods().size();
 
-    const Interface *ancestor = this;
+    const Interface *ancestor = mSuperType;
     while (ancestor != nullptr) {
-        serial += ancestor->methods().size();
+        serial += ancestor->userDefinedMethods().size();
         ancestor = ancestor->superType();
     }
 
+    CHECK(serial <= LAST_CALL_TRANSACTION) << "More than "
+            << LAST_CALL_TRANSACTION << " methods are not allowed.";
     method->setSerialId(serial);
-    mMethods.push_back(method);
+    mUserMethods.push_back(method);
 
     return true;
 }
 
+
 const Interface *Interface::superType() const {
     return mSuperType;
 }
 
+std::vector<const Interface *> Interface::typeChain() const {
+    std::vector<const Interface *> v;
+    const Interface *iface = this;
+    while (iface != nullptr) {
+        v.push_back(iface);
+        iface = iface->mSuperType;
+    }
+    return v;
+}
+
 bool Interface::isInterface() const {
     return true;
 }
@@ -71,19 +139,41 @@
     return true;
 }
 
-const std::vector<Method *> &Interface::methods() const {
-    return mMethods;
+const std::vector<Method *> &Interface::userDefinedMethods() const {
+    return mUserMethods;
+}
+
+const std::vector<Method *> &Interface::hidlReservedMethods() const {
+    return mReservedMethods;
+}
+
+std::vector<Method *> Interface::methods() const {
+    std::vector<Method *> v(mUserMethods);
+    v.insert(v.end(), mReservedMethods.begin(), mReservedMethods.end());
+    return v;
+}
+
+std::vector<InterfaceAndMethod> Interface::allMethodsFromRoot() const {
+    std::vector<InterfaceAndMethod> v;
+    std::vector<const Interface *> chain = typeChain();
+    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
+        const Interface *iface = *it;
+        for (Method *userMethod : iface->userDefinedMethods()) {
+            v.push_back(InterfaceAndMethod(iface, userMethod));
+        }
+    }
+    for (Method *reservedMethod : hidlReservedMethods()) {
+        v.push_back(InterfaceAndMethod(this, reservedMethod));
+    }
+    return v;
 }
 
 Method *Interface::lookupMethod(std::string name) const {
-    const Interface *ancestor = this;
-    while (ancestor != nullptr) {
-        for (const auto &method : mMethods) {
-            if (method->name() == name) {
-                return method;
-            }
+    for (const auto &tuple : allMethodsFromRoot()) {
+        Method *method = tuple.method();
+        if (method->name() == name) {
+            return method;
         }
-        ancestor = ancestor->superType();
     }
 
     return nullptr;
@@ -228,7 +318,7 @@
 }
 
 status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
-    for (const auto &method : mMethods) {
+    for (const auto &method : methods()) {
         out << "api: {\n";
         out.indent();
         out << "name: \"" << method->name() << "\"\n";
@@ -297,7 +387,7 @@
 
 
 bool Interface::hasOnewayMethods() const {
-    for (auto const &method : mMethods) {
+    for (auto const &method : methods()) {
         if (method->isOneway()) {
             return true;
         }
@@ -334,7 +424,7 @@
         return false;
     }
 
-    for (const auto &method : mMethods) {
+    for (const auto &method : methods()) {
         if (!method->isJavaCompatible()) {
             mIsJavaCompatibleInProgress = false;
             return false;
diff --git a/Interface.h b/Interface.h
index 7f7edc7..ae7e032 100644
--- a/Interface.h
+++ b/Interface.h
@@ -19,10 +19,12 @@
 #define INTERFACE_H_
 
 #include "Scope.h"
+#include <vector>
 
 namespace android {
 
 struct Method;
+struct InterfaceAndMethod;
 
 struct Interface : public Scope {
     Interface(const char *localName, Interface *super);
@@ -34,8 +36,26 @@
 
     const Interface *superType() const;
 
-    const std::vector<Method *> &methods() const;
     Method *lookupMethod(std::string name) const;
+    // Super type chain to root type, including myself.
+    // First element is this.
+    std::vector<const Interface *> typeChain() const;
+
+    // user defined methods (explicit definition in HAL files)
+    const std::vector<Method *> &userDefinedMethods() const;
+    // HIDL reserved methods (every interface has these implicitly defined)
+    const std::vector<Method *> &hidlReservedMethods() const;
+    // the sum of userDefinedMethods() and hidlReservedMethods().
+    std::vector<Method *> methods() const;
+
+    // userDefinedMethods() for all super type + methods()
+    // The order will be as follows (in the transaction code order):
+    // great-great-...-great-grand parent->userDefinedMethods()
+    // ...
+    // parent->userDefinedMethods()
+    // this->userDefinedMethods()
+    // this->hidlReservedMethods()
+    std::vector<InterfaceAndMethod> allMethodsFromRoot() const;
 
     std::string getBaseName() const;
 
@@ -72,12 +92,27 @@
 
 private:
     Interface *mSuperType;
-    std::vector<Method *> mMethods;
+    std::vector<Method *> mUserMethods;
+    std::vector<Method *> mReservedMethods;
     mutable bool mIsJavaCompatibleInProgress;
+    Method *createDescriptorChainMethod() const;
 
     DISALLOW_COPY_AND_ASSIGN(Interface);
 };
 
+// An interface / method tuple.
+struct InterfaceAndMethod {
+    InterfaceAndMethod(const Interface *iface, Method *method)
+        : mInterface(iface),
+          mMethod(method) {}
+    Method *method() const { return mMethod; }
+    const Interface *interface() const { return mInterface; }
+private:
+    // do not own these objects.
+    const Interface *mInterface;
+    Method *mMethod;
+};
+
 }  // namespace android
 
 #endif  // INTERFACE_H_
diff --git a/Method.cpp b/Method.cpp
index 95a688a..dfac662 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -20,6 +20,7 @@
 #include "ScalarType.h"
 #include "Type.h"
 
+#include <android-base/logging.h>
 #include <hidl-util/Formatter.h>
 
 namespace android {
@@ -36,6 +37,24 @@
       mAnnotations(annotations) {
 }
 
+// HIDL reserved methods.
+Method::Method(const char *name,
+       std::vector<TypedVar *> *args,
+       std::vector<TypedVar *> *results,
+       bool oneway,
+       std::vector<Annotation *> *annotations,
+       size_t serial,
+       MethodImpl cppImpl,
+       MethodImpl javaImpl)
+    : Method(name, args, results, oneway, annotations) {
+
+    mIsHidlReserved = true;
+    mSerial = serial;
+    mCppImpl = cppImpl;
+    mJavaImpl = javaImpl;
+}
+
+
 std::string Method::name() const {
     return mName;
 }
@@ -52,7 +71,22 @@
     return *mAnnotations;
 }
 
+void Method::cppImpl(Formatter &out) const {
+    CHECK(mIsHidlReserved);
+    if (mCppImpl) {
+        mCppImpl(out);
+    }
+}
+
+void Method::javaImpl(Formatter &out) const {
+    CHECK(mIsHidlReserved);
+    if (mJavaImpl) {
+        mJavaImpl(out);
+    }
+}
+
 void Method::setSerialId(size_t serial) {
+    CHECK(!mIsHidlReserved);
     mSerial = serial;
 }
 
diff --git a/Method.h b/Method.h
index 3c84914..7e711f0 100644
--- a/Method.h
+++ b/Method.h
@@ -19,6 +19,8 @@
 #define METHOD_H_
 
 #include <android-base/macros.h>
+#include <functional>
+#include <hidl-util/Formatter.h>
 #include <string>
 #include <vector>
 
@@ -30,17 +32,30 @@
 struct Type;
 struct TypedVar;
 
+using MethodImpl = std::function<void(Formatter &)>;
+
 struct Method {
     Method(const char *name,
            std::vector<TypedVar *> *args,
            std::vector<TypedVar *> *results,
            bool oneway,
            std::vector<Annotation *> *annotations);
+    Method(const char *name,
+           std::vector<TypedVar *> *args,
+           std::vector<TypedVar *> *results,
+           bool oneway,
+           std::vector<Annotation *> *annotations,
+           size_t serial,
+           MethodImpl cppImpl,
+           MethodImpl javaImpl);
 
     std::string name() const;
     const std::vector<TypedVar *> &args() const;
     const std::vector<TypedVar *> &results() const;
     bool isOneway() const { return mOneway; }
+    void cppImpl(Formatter &out) const;
+    void javaImpl(Formatter &out) const;
+    bool isHidlReserved() const { return mIsHidlReserved; }
     const std::vector<Annotation *> &annotations() const;
 
     void setSerialId(size_t serial);
@@ -68,6 +83,12 @@
     bool mOneway;
     std::vector<Annotation *> *mAnnotations;
 
+    bool mIsHidlReserved = false;
+    // The following fields has no meaning if mIsHidlReserved is false.
+    // hard-coded implementation for HIDL reserved methods.
+    MethodImpl mCppImpl = nullptr;
+    MethodImpl mJavaImpl = nullptr;
+
     DISALLOW_COPY_AND_ASSIGN(Method);
 };
 
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 2c06990..921d6ae 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -169,7 +169,7 @@
         const Interface *superType = iface->superType();
 
         if (superType == NULL) {
-            out << " : virtual public RefBase";
+            out << " : virtual public IHidlInterfaceBase";
         } else {
             out << " : virtual public "
                 << superType->fullName();
@@ -199,7 +199,7 @@
         out << "return version;\n";
         out.unindent();
         out << "}\n\n";
-        out << "virtual bool isRemote() const { return false; }\n\n";
+        out << "virtual bool isRemote() const override { return false; }\n\n";
         bool haveCallbacks = false;
         for (const auto &method : iface->methods()) {
             const bool returnsValue = !method->results().empty();
@@ -253,9 +253,21 @@
                 out << method->name() << "_cb _hidl_cb";
             }
 
-            out << ") = 0;\n";
+            out << ")";
+            if (method->isHidlReserved()) {
+                out << " override";
+                out << " {\n";
+                out.indent();
+                method->cppImpl(out);
+                out.unindent();
+                out << "\n}\n";
+            } else {
+                out << " = 0;\n";
+            }
         }
 
+        out << "\nstatic const ::android::String16 descriptor;\n\n";
+
         out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
     }
 
@@ -504,65 +516,64 @@
 
     const Interface *iface = mRootScope->getInterface();
 
-    std::vector<const Interface *> chain;
-    while (iface != NULL) {
-        chain.push_back(iface);
-        iface = iface->superType();
-    }
+    const Interface *prevIterface = nullptr;
+    for (const auto &tuple : iface->allMethodsFromRoot()) {
+        const Method *method = tuple.method();
+        const Interface *superInterface = tuple.interface();
 
-    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
-        const Interface *superInterface = *it;
-
-        out << "// Methods from "
-            << superInterface->fullName()
-            << " follow.\n";
-
-        for (const auto &method : superInterface->methods()) {
-            status_t err;
-            switch(type) {
-                case STUB_HEADER:
-                    err = generateStubMethod(out,
+        if(prevIterface != superInterface) {
+            if (prevIterface != nullptr) {
+                out << "\n";
+            }
+            out << "// Methods from "
+                << superInterface->fullName()
+                << " follow.\n";
+            prevIterface = superInterface;
+        }
+        status_t err;
+        switch(type) {
+            case STUB_HEADER:
+                err = generateStubMethod(out,
+                                         className,
+                                         method,
+                                         specifyNamespaces);
+                break;
+            case PROXY_HEADER:
+                err = generateProxyDeclaration(out,
+                                               className,
+                                               method,
+                                               specifyNamespaces);
+                break;
+            case IMPL_HEADER:
+                err = generateStubImplDeclaration(out,
+                                                  className,
+                                                  method,
+                                                  specifyNamespaces);
+                break;
+            case IMPL_SOURCE:
+                err = generateStubImplMethod(out,
                                              className,
                                              method,
                                              specifyNamespaces);
-                    break;
-                case PROXY_HEADER:
-                    err = generateProxyDeclaration(out,
-                                                   className,
-                                                   method,
-                                                   specifyNamespaces);
-                    break;
-                case IMPL_HEADER:
-                    err = generateStubImplDeclaration(out,
-                                                      className,
-                                                      method,
-                                                      specifyNamespaces);
-                    break;
-                case IMPL_SOURCE:
-                    err = generateStubImplMethod(out,
-                                                 className,
-                                                 method,
-                                                 specifyNamespaces);
-                    break;
-                case PASSTHROUGH_HEADER:
-                    err = generatePassthroughMethod(out,
-                                                    className,
-                                                    method,
-                                                    specifyNamespaces);
-                    break;
-                default:
-                    LOG(ERROR) << "Unkown method type: " << type;
-                    err = UNKNOWN_ERROR;
-            }
-
-            if (err != OK) {
-                return err;
-            }
+                break;
+            case PASSTHROUGH_HEADER:
+                err = generatePassthroughMethod(out,
+                                                className,
+                                                method,
+                                                specifyNamespaces);
+                break;
+            default:
+                LOG(ERROR) << "Unkown method type: " << type;
+                err = UNKNOWN_ERROR;
         }
 
-        out << "\n";
+        if (err != OK) {
+            return err;
+        }
     }
 
+    out << "\n";
+
     return OK;
 }
 
@@ -711,7 +722,7 @@
         << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
         << "\n\n";
 
-    out << "virtual bool isRemote() const { return true; }\n\n";
+    out << "virtual bool isRemote() const override { return true; }\n\n";
 
     status_t err = generateMethods(out,
                                    "" /* class name */,
@@ -793,7 +804,16 @@
     status_t err = generateTypeSource(out, ifaceName);
 
     if (err == OK && isInterface) {
+        const Interface *iface = mRootScope->getInterface();
         out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
+
+        // need to be put here, generateStubSource is using this.
+        out << "const ::android::String16 I"
+            << iface->getBaseName()
+            << "::descriptor(\""
+            << iface->fqName().string()
+            << "\");\n\n";
+
         err = generateProxySource(out, baseName);
     }
 
@@ -930,181 +950,178 @@
 
     const Interface *iface = mRootScope->getInterface();
 
-    std::vector<const Interface *> chain;
-    while (iface != NULL) {
-        chain.push_back(iface);
-        iface = iface->superType();
-    }
+    for (const auto &tuple : iface->allMethodsFromRoot()) {
+        const Method *method = tuple.method();
+        const Interface *superInterface = tuple.interface();
+        method->generateCppSignature(out,
+                                     klassName,
+                                     true /* specify namespaces */);
 
-    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
-        const Interface *superInterface = *it;
+        const bool returnsValue = !method->results().empty();
+        const TypedVar *elidedReturn = method->canElideCallback();
 
-        for (const auto &method : superInterface->methods()) {
-            method->generateCppSignature(out,
-                                         klassName,
-                                         true /* specify namespaces */);
+        out << "{\n";
 
-            const bool returnsValue = !method->results().empty();
-            const TypedVar *elidedReturn = method->canElideCallback();
+        out.indent();
 
-            out << "{\n";
+        if (returnsValue && elidedReturn == nullptr) {
+            generateCheckNonNull(out, "_hidl_cb");
+        }
 
-            out.indent();
+        status_t status = generateCppInstrumentationCall(
+                out,
+                InstrumentationEvent::CLIENT_API_ENTRY,
+                superInterface,
+                method);
+        if (status != OK) {
+            return status;
+        }
 
-            if (returnsValue && elidedReturn == nullptr) {
-                generateCheckNonNull(out, "_hidl_cb");
+        out << "::android::hardware::Parcel _hidl_data;\n";
+        out << "::android::hardware::Parcel _hidl_reply;\n";
+        out << "::android::status_t _hidl_err;\n";
+        out << "::android::hardware::Status _hidl_status;\n\n";
+
+        declareCppReaderLocals(
+                out, method->results(), true /* forResults */);
+
+        out << "_hidl_err = _hidl_data.writeInterfaceToken(";
+        if (!method->isHidlReserved()) {
+            out << superInterface->fqName().cppNamespace()
+                << "::IHw"
+                << superInterface->getBaseName();
+        } else {
+            out << "::android::hardware::IHidlInterfaceBase";
+        }
+        out << "::descriptor);\n";
+
+        out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+
+        // First DFS: write all buffers and resolve pointers for parent
+        for (const auto &arg : method->args()) {
+            emitCppReaderWriter(
+                    out,
+                    "_hidl_data",
+                    false /* parcelObjIsPointer */,
+                    arg,
+                    false /* reader */,
+                    Type::ErrorMode_Goto,
+                    false /* addPrefixToName */);
+        }
+
+        // Second DFS: resolve references.
+        for (const auto &arg : method->args()) {
+            emitCppResolveReferences(
+                    out,
+                    "_hidl_data",
+                    false /* parcelObjIsPointer */,
+                    arg,
+                    false /* reader */,
+                    Type::ErrorMode_Goto,
+                    false /* addPrefixToName */);
+        }
+
+        out << "_hidl_err = remote()->transact("
+            << method->getSerialId()
+            << " /* "
+            << method->name()
+            << " */, _hidl_data, &_hidl_reply";
+
+        if (method->isOneway()) {
+            out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
+        }
+        out << ");\n";
+
+        out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+
+        if (!method->isOneway()) {
+            out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
+            out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+            out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
+
+
+            // First DFS: write all buffers and resolve pointers for parent
+            for (const auto &arg : method->results()) {
+                emitCppReaderWriter(
+                        out,
+                        "_hidl_reply",
+                        false /* parcelObjIsPointer */,
+                        arg,
+                        true /* reader */,
+                        Type::ErrorMode_Goto,
+                        true /* addPrefixToName */);
             }
 
+            // Second DFS: resolve references.
+            for (const auto &arg : method->results()) {
+                emitCppResolveReferences(
+                        out,
+                        "_hidl_reply",
+                        false /* parcelObjIsPointer */,
+                        arg,
+                        true /* reader */,
+                        Type::ErrorMode_Goto,
+                        true /* addPrefixToName */);
+            }
+
+            if (returnsValue && elidedReturn == nullptr) {
+                out << "_hidl_cb(";
+
+                bool first = true;
+                for (const auto &arg : method->results()) {
+                    if (!first) {
+                        out << ", ";
+                    }
+
+                    if (arg->type().resultNeedsDeref()) {
+                        out << "*";
+                    }
+                    out << "_hidl_out_" << arg->name();
+
+                    first = false;
+                }
+
+                out << ");\n\n";
+            }
             status_t status = generateCppInstrumentationCall(
                     out,
-                    InstrumentationEvent::CLIENT_API_ENTRY,
+                    InstrumentationEvent::CLIENT_API_EXIT,
                     superInterface,
                     method);
             if (status != OK) {
                 return status;
             }
+        }
 
-            out << "::android::hardware::Parcel _hidl_data;\n";
-            out << "::android::hardware::Parcel _hidl_reply;\n";
-            out << "::android::status_t _hidl_err;\n";
-            out << "::android::hardware::Status _hidl_status;\n\n";
-
-            declareCppReaderLocals(
-                    out, method->results(), true /* forResults */);
-
-            out << "_hidl_err = _hidl_data.writeInterfaceToken("
-                << superInterface->fqName().cppNamespace()
-                << "::IHw"
-                << superInterface->getBaseName()
-                << "::descriptor);\n";
-
-            out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-
-            // First DFS: write all buffers and resolve pointers for parent
-            for (const auto &arg : method->args()) {
-                emitCppReaderWriter(
-                        out,
-                        "_hidl_data",
-                        false /* parcelObjIsPointer */,
-                        arg,
-                        false /* reader */,
-                        Type::ErrorMode_Goto,
-                        false /* addPrefixToName */);
-            }
-
-            // Second DFS: resolve references.
-            for (const auto &arg : method->args()) {
-                emitCppResolveReferences(
-                        out,
-                        "_hidl_data",
-                        false /* parcelObjIsPointer */,
-                        arg,
-                        false /* reader */,
-                        Type::ErrorMode_Goto,
-                        false /* addPrefixToName */);
-            }
-
-            out << "_hidl_err = remote()->transact("
-                << method->getSerialId()
-                << " /* "
-                << method->name()
-                << " */, _hidl_data, &_hidl_reply";
-
-            if (method->isOneway()) {
-                out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
-            }
-            out << ");\n";
-
-            out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-
-            if (!method->isOneway()) {
-                out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
-                out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-                out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
-
-
-                // First DFS: write all buffers and resolve pointers for parent
-                for (const auto &arg : method->results()) {
-                    emitCppReaderWriter(
-                            out,
-                            "_hidl_reply",
-                            false /* parcelObjIsPointer */,
-                            arg,
-                            true /* reader */,
-                            Type::ErrorMode_Goto,
-                            true /* addPrefixToName */);
-                }
-
-                // Second DFS: resolve references.
-                for (const auto &arg : method->results()) {
-                    emitCppResolveReferences(
-                            out,
-                            "_hidl_reply",
-                            false /* parcelObjIsPointer */,
-                            arg,
-                            true /* reader */,
-                            Type::ErrorMode_Goto,
-                            true /* addPrefixToName */);
-                }
-
-                if (returnsValue && elidedReturn == nullptr) {
-                    out << "_hidl_cb(";
-
-                    bool first = true;
-                    for (const auto &arg : method->results()) {
-                        if (!first) {
-                            out << ", ";
-                        }
-
-                        if (arg->type().resultNeedsDeref()) {
-                            out << "*";
-                        }
-                        out << "_hidl_out_" << arg->name();
-
-                        first = false;
-                    }
-
-                    out << ");\n\n";
-                }
-                status_t status = generateCppInstrumentationCall(
-                        out,
-                        InstrumentationEvent::CLIENT_API_EXIT,
-                        superInterface,
-                        method);
-                if (status != OK) {
-                    return status;
-                }
-            }
-
-            if (elidedReturn != nullptr) {
-                std::string extra;
-                out << "_hidl_status.setFromStatusT(_hidl_err);\n";
-                out << "return ::android::hardware::Return<";
-                out << elidedReturn->type().getCppResultType(&extra)
-                    << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
-            } else {
-                out << "_hidl_status.setFromStatusT(_hidl_err);\n";
-                out << "return ::android::hardware::Return<void>();\n\n";
-            }
-
-            out.unindent();
-            out << "_hidl_error:\n";
-            out.indent();
+        if (elidedReturn != nullptr) {
+            std::string extra;
             out << "_hidl_status.setFromStatusT(_hidl_err);\n";
             out << "return ::android::hardware::Return<";
-            if (elidedReturn != nullptr) {
-                std::string extra;
-                out << method->results().at(0)->type().getCppResultType(&extra);
-            } else {
-                out << "void";
-            }
-            out << ">(_hidl_status);\n";
-
-            out.unindent();
-            out << "}\n\n";
+            out << elidedReturn->type().getCppResultType(&extra)
+                << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
+        } else {
+            out << "_hidl_status.setFromStatusT(_hidl_err);\n";
+            out << "return ::android::hardware::Return<void>();\n\n";
         }
+
+        out.unindent();
+        out << "_hidl_error:\n";
+        out.indent();
+        out << "_hidl_status.setFromStatusT(_hidl_err);\n";
+        out << "return ::android::hardware::Return<";
+        if (elidedReturn != nullptr) {
+            std::string extra;
+            out << method->results().at(0)->type().getCppResultType(&extra);
+        } else {
+            out << "void";
+        }
+        out << ">(_hidl_status);\n";
+
+        out.unindent();
+        out << "}\n\n";
     }
 
+
     return OK;
 }
 
@@ -1112,11 +1129,11 @@
         Formatter &out, const std::string &baseName) const {
     out << "IMPLEMENT_HWBINDER_META_INTERFACE("
         << baseName
-        << ", \""
-        << mPackage.string()
+        << ", "
+        << mPackage.cppNamespace()
         << "::I"
         << baseName
-        << "\");\n\n";
+        << "::descriptor);\n\n";
 
     const std::string klassName = "Bn" + baseName;
 
@@ -1163,34 +1180,26 @@
 
     const Interface *iface = mRootScope->getInterface();
 
-    std::vector<const Interface *> chain;
-    while (iface != NULL) {
-        chain.push_back(iface);
-        iface = iface->superType();
-    }
+    for (const auto &tuple : iface->allMethodsFromRoot()) {
+        const Method *method = tuple.method();
+        const Interface *superInterface = tuple.interface();
+        out << "case "
+            << method->getSerialId()
+            << " /* "
+            << method->name()
+            << " */:\n{\n";
 
-    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
-        const Interface *superInterface = *it;
+        out.indent();
 
-        for (const auto &method : superInterface->methods()) {
-            out << "case "
-                << method->getSerialId()
-                << " /* "
-                << method->name()
-                << " */:\n{\n";
+        status_t err =
+            generateStubSourceForMethod(out, superInterface, method);
 
-            out.indent();
-
-            status_t err =
-                generateStubSourceForMethod(out, superInterface, method);
-
-            if (err != OK) {
-                return err;
-            }
-
-            out.unindent();
-            out << "}\n\n";
+        if (err != OK) {
+            return err;
         }
+
+        out.unindent();
+        out << "}\n\n";
     }
 
     out << "default:\n{\n";
@@ -1242,11 +1251,17 @@
 
 status_t AST::generateStubSourceForMethod(
         Formatter &out, const Interface *iface, const Method *method) const {
-    out << "if (!_hidl_data.enforceInterface("
-        << iface->fqName().cppNamespace()
-        << "::IHw"
-        << iface->getBaseName()
-        << "::descriptor)) {\n";
+    out << "if (!_hidl_data.enforceInterface(";
+
+    if (!method->isHidlReserved()) {
+        out << iface->fqName().cppNamespace()
+            << "::IHw"
+            << iface->getBaseName();
+    } else {
+        out << "::android::hardware::IHidlInterfaceBase";
+    }
+
+    out << "::descriptor)) {\n";
 
     out.indent();
     out << "_hidl_err = ::android::BAD_TYPE;\n";
diff --git a/generateCppImpl.cpp b/generateCppImpl.cpp
index 66a35d4..b8b91c4 100644
--- a/generateCppImpl.cpp
+++ b/generateCppImpl.cpp
@@ -137,27 +137,22 @@
     // this is namespace aware code and doesn't require post-processing
     out.setNamespace("");
 
-    const Interface *ancestor = iface;
-    std::vector<const Interface *> chain;
-    while (ancestor != NULL) {
-        chain.push_back(ancestor);
-        ancestor = ancestor->superType();
-    }
+    std::vector<const Interface *> chain = iface->typeChain();
 
     std::set<const FQName> usedTypes{};
 
     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
         const Interface *superInterface = *it;
-
         superInterface->addNamedTypesToSet(usedTypes);
+    }
 
-        for (const auto &method : superInterface->methods()) {
-            for(const auto & arg : method->args()) {
-                arg->type().addNamedTypesToSet(usedTypes);
-            }
-            for(const auto & results : method->results()) {
-                results->type().addNamedTypesToSet(usedTypes);
-            }
+    for (const auto &tuple : iface->allMethodsFromRoot()) {
+        const Method *method = tuple.method();
+        for(const auto & arg : method->args()) {
+            arg->type().addNamedTypesToSet(usedTypes);
+        }
+        for(const auto & results : method->results()) {
+            results->type().addNamedTypesToSet(usedTypes);
         }
     }
 
diff --git a/generateJava.cpp b/generateJava.cpp
index 69ce0d1..63643e1 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -304,119 +304,114 @@
     out.unindent();
     out << "}\n\n";
 
-    std::vector<const Interface *> chain;
-    while (iface != NULL) {
-        chain.push_back(iface);
-        iface = iface->superType();
-    }
+    const Interface *prevInterface = nullptr;
+    for (const auto &tuple : iface->allMethodsFromRoot()) {
+        const Method *method = tuple.method();
+        const Interface *superInterface = tuple.interface();
+        if (prevInterface != superInterface) {
+            out << "// Methods from "
+                << superInterface->fullName()
+                << " follow.\n";
+            prevInterface = superInterface;
+        }
+        const bool returnsValue = !method->results().empty();
+        const bool needsCallback = method->results().size() > 1;
 
-    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
-        const Interface *superInterface = *it;
+        out << "public ";
+        if (returnsValue && !needsCallback) {
+            std::string extra;
+            out << method->results()[0]->type().getJavaType(&extra)
+                << extra;
+        } else {
+            out << "void";
+        }
 
-        out << "// Methods from "
-            << superInterface->fullName()
-            << " follow.\n";
+        out << " "
+            << method->name()
+            << "("
+            << Method::GetJavaArgSignature(method->args());
 
-        for (const auto &method : superInterface->methods()) {
-            const bool returnsValue = !method->results().empty();
-            const bool needsCallback = method->results().size() > 1;
-
-            out << "public ";
-            if (returnsValue && !needsCallback) {
-                std::string extra;
-                out << method->results()[0]->type().getJavaType(&extra)
-                    << extra;
-            } else {
-                out << "void";
+        if (needsCallback) {
+            if (!method->args().empty()) {
+                out << ", ";
             }
 
-            out << " "
-                << method->name()
-                << "("
-                << Method::GetJavaArgSignature(method->args());
+            out << method->name()
+                << "Callback cb";
+        }
 
-            if (needsCallback) {
-                if (!method->args().empty()) {
-                    out << ", ";
-                }
+        out << ") {\n";
+        out.indent();
 
-                out << method->name()
-                    << "Callback cb";
-            }
+        out << "HwParcel request = new HwParcel();\n";
+        out << "request.writeInterfaceToken("
+            << superInterface->fullJavaName()
+            << ".kInterfaceName);\n";
 
-            out << ") {\n";
-            out.indent();
+        for (const auto &arg : method->args()) {
+            emitJavaReaderWriter(
+                    out,
+                    "request",
+                    arg,
+                    false /* isReader */);
+        }
 
-            out << "HwParcel request = new HwParcel();\n";
-            out << "request.writeInterfaceToken("
-                << superInterface->fullJavaName()
-                << ".kInterfaceName);\n";
+        out << "\nHwParcel reply = new HwParcel();\n"
+            << "mRemote.transact("
+            << method->getSerialId()
+            << " /* "
+            << method->name()
+            << " */, request, reply, ";
 
-            for (const auto &arg : method->args()) {
+        if (method->isOneway()) {
+            out << "IHwBinder.FLAG_ONEWAY";
+        } else {
+            out << "0 /* flags */";
+        }
+
+        out << ");\n";
+
+        if (!method->isOneway()) {
+            out << "reply.verifySuccess();\n";
+        } else {
+            CHECK(!returnsValue);
+        }
+
+        out << "request.releaseTemporaryStorage();\n";
+
+        if (returnsValue) {
+            out << "\n";
+
+            for (const auto &arg : method->results()) {
                 emitJavaReaderWriter(
                         out,
-                        "request",
+                        "reply",
                         arg,
-                        false /* isReader */);
+                        true /* isReader */);
             }
 
-            out << "\nHwParcel reply = new HwParcel();\n"
-                << "mRemote.transact("
-                << method->getSerialId()
-                << " /* "
-                << method->name()
-                << " */, request, reply, ";
+            if (needsCallback) {
+                out << "cb.onValues(";
 
-            if (method->isOneway()) {
-                out << "IHwBinder.FLAG_ONEWAY";
-            } else {
-                out << "0 /* flags */";
-            }
-
-            out << ");\n";
-
-            if (!method->isOneway()) {
-                out << "reply.verifySuccess();\n";
-            } else {
-                CHECK(!returnsValue);
-            }
-
-            out << "request.releaseTemporaryStorage();\n";
-
-            if (returnsValue) {
-                out << "\n";
-
+                bool firstField = true;
                 for (const auto &arg : method->results()) {
-                    emitJavaReaderWriter(
-                            out,
-                            "reply",
-                            arg,
-                            true /* isReader */);
-                }
-
-                if (needsCallback) {
-                    out << "cb.onValues(";
-
-                    bool firstField = true;
-                    for (const auto &arg : method->results()) {
-                        if (!firstField) {
-                            out << ", ";
-                        }
-
-                        out << arg->name();
-                        firstField = false;
+                    if (!firstField) {
+                        out << ", ";
                     }
 
-                    out << ");\n";
-                } else {
-                    const std::string returnName = method->results()[0]->name();
-                    out << "return " << returnName << ";\n";
+                    out << arg->name();
+                    firstField = false;
                 }
-            }
 
-            out.unindent();
-            out << "}\n\n";
+                out << ");\n";
+            } else {
+                const std::string returnName = method->results()[0]->name();
+                out << "return " << returnName << ";\n";
+            }
         }
+
+        out.unindent();
+        out << "}\n\n";
     }
 
     out.unindent();
@@ -436,6 +431,21 @@
     out.unindent();
     out << "}\n\n";
 
+    // b/32383557 this is a hack. We need to change this if we have more reserved methods.
+    for (Method *method : iface->hidlReservedMethods()) {
+        std::string extra;
+        out << "public final "
+            << method->results()[0]->type().getJavaType(&extra)
+            << extra
+            << " "
+            << method->name()
+            << "() {\n";
+        out.indent();
+        method->javaImpl(out);
+        out.unindent();
+        out << "\n}\n\n";
+    }
+
     out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
     out.indent();
     // XXX what about potential superClasses?
@@ -470,111 +480,109 @@
 
     out.indent();
 
-    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
-        const Interface *superInterface = *it;
+    for (const auto &tuple : iface->allMethodsFromRoot()) {
+        const Method *method = tuple.method();
+        const Interface *superInterface = tuple.interface();
+        const bool returnsValue = !method->results().empty();
+        const bool needsCallback = method->results().size() > 1;
 
-        for (const auto &method : superInterface->methods()) {
-            const bool returnsValue = !method->results().empty();
-            const bool needsCallback = method->results().size() > 1;
+        out << "case "
+            << method->getSerialId()
+            << " /* "
+            << method->name()
+            << " */:\n{\n";
 
-            out << "case "
-                << method->getSerialId()
-                << " /* "
-                << method->name()
-                << " */:\n{\n";
+        out.indent();
 
+        out << "request.enforceInterface("
+            << superInterface->fullJavaName()
+            << ".kInterfaceName);\n\n";
+
+        for (const auto &arg : method->args()) {
+            emitJavaReaderWriter(
+                    out,
+                    "request",
+                    arg,
+                    true /* isReader */);
+        }
+
+        if (!needsCallback && returnsValue) {
+            const TypedVar *returnArg = method->results()[0];
+            std::string extra;
+
+            out << returnArg->type().getJavaType(&extra)
+                << extra
+                << " "
+                << returnArg->name()
+                << " = ";
+        }
+
+        out << method->name()
+            << "(";
+
+        bool firstField = true;
+        for (const auto &arg : method->args()) {
+            if (!firstField) {
+                out << ", ";
+            }
+
+            out << arg->name();
+
+            firstField = false;
+        }
+
+        if (needsCallback) {
+            if (!firstField) {
+                out << ", ";
+            }
+
+            out << "new " << method->name() << "Callback() {\n";
             out.indent();
 
-            out << "request.enforceInterface("
-                << superInterface->fullJavaName()
-                << ".kInterfaceName);\n\n";
+            out << "@Override\n"
+                << "public void onValues("
+                << Method::GetJavaArgSignature(method->results())
+                << ") {\n";
 
-            for (const auto &arg : method->args()) {
+            out.indent();
+            out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
+
+            for (const auto &arg : method->results()) {
                 emitJavaReaderWriter(
                         out,
-                        "request",
+                        "reply",
                         arg,
-                        true /* isReader */);
+                        false /* isReader */);
             }
 
-            if (!needsCallback && returnsValue) {
-                const TypedVar *returnArg = method->results()[0];
-                std::string extra;
+            out << "reply.send();\n"
+                      << "}}";
 
-                out << returnArg->type().getJavaType(&extra)
-                    << extra
-                    << " "
-                    << returnArg->name()
-                    << " = ";
-            }
-
-            out << method->name()
-                << "(";
-
-            bool firstField = true;
-            for (const auto &arg : method->args()) {
-                if (!firstField) {
-                    out << ", ";
-                }
-
-                out << arg->name();
-
-                firstField = false;
-            }
-
-            if (needsCallback) {
-                if (!firstField) {
-                    out << ", ";
-                }
-
-                out << "new " << method->name() << "Callback() {\n";
-                out.indent();
-
-                out << "@Override\n"
-                    << "public void onValues("
-                    << Method::GetJavaArgSignature(method->results())
-                    << ") {\n";
-
-                out.indent();
-                out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
-
-                for (const auto &arg : method->results()) {
-                    emitJavaReaderWriter(
-                            out,
-                            "reply",
-                            arg,
-                            false /* isReader */);
-                }
-
-                out << "reply.send();\n"
-                          << "}}";
-
-                out.unindent();
-                out.unindent();
-            }
-
-            out << ");\n";
-
-            if (!needsCallback) {
-                out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
-
-                if (returnsValue) {
-                    const TypedVar *returnArg = method->results()[0];
-
-                    emitJavaReaderWriter(
-                            out,
-                            "reply",
-                            returnArg,
-                            false /* isReader */);
-                }
-
-                out << "reply.send();\n";
-            }
-
-            out << "break;\n";
             out.unindent();
-            out << "}\n\n";
+            out.unindent();
         }
+
+        out << ");\n";
+
+        if (!needsCallback) {
+            out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
+
+            if (returnsValue) {
+                const TypedVar *returnArg = method->results()[0];
+
+                emitJavaReaderWriter(
+                        out,
+                        "reply",
+                        returnArg,
+                        false /* isReader */);
+            }
+
+            out << "reply.send();\n";
+        }
+
+        out << "break;\n";
+        out.unindent();
+        out << "}\n\n";
     }
 
     out.unindent();
diff --git a/generateVts.cpp b/generateVts.cpp
index 2eba598..35eb0d0 100644
--- a/generateVts.cpp
+++ b/generateVts.cpp
@@ -121,11 +121,7 @@
         out << "interface: {\n";
         out.indent();
 
-        std::vector<const Interface *> chain;
-        while (iface != NULL) {
-            chain.push_back(iface);
-            iface = iface->superType();
-        }
+        std::vector<const Interface *> chain = iface->typeChain();
 
         // Generate all the attribute declarations first.
         for (auto it = chain.rbegin(); it != chain.rend(); ++it) {