Add interfaceDescriptor() method to all interfaces

which returns interfaceChain[0].

Bug: 34136228
Test: hidl_test
Test: hidl_test_java
Change-Id: Id0d8139d51f39b1c317d966b305e883e561241b8
diff --git a/Interface.cpp b/Interface.cpp
index 9d7cc89..01cc063 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -47,6 +47,7 @@
     /////////////////// HIDL reserved
     FIRST_HIDL_TRANSACTION  = 0x00f00000,
     HIDL_DESCRIPTOR_CHAIN_TRANSACTION = FIRST_HIDL_TRANSACTION,
+    HIDL_GET_DESCRIPTOR_TRANSACTION,
     HIDL_SYSPROPS_CHANGED_TRANSACTION,
     HIDL_LINK_TO_DEATH_TRANSACTION,
     HIDL_UNLINK_TO_DEATH_TRANSACTION,
@@ -59,6 +60,7 @@
       mSuperType(super),
       mIsJavaCompatibleInProgress(false) {
     mReservedMethods.push_back(createDescriptorChainMethod());
+    mReservedMethods.push_back(createGetDescriptorMethod());
     mReservedMethods.push_back(createSyspropsChangedMethod());
     mReservedMethods.push_back(createLinkToDeathMethod());
     mReservedMethods.push_back(createUnlinkToDeathMethod());
@@ -223,7 +225,7 @@
     VectorType *vecType = new VectorType();
     vecType->setElementType(new StringType());
     std::vector<TypedVar *> *results = new std::vector<TypedVar *>();
-    results->push_back(new TypedVar("indicator", vecType));
+    results->push_back(new TypedVar("descriptors", vecType));
 
     return new Method("interfaceChain",
         new std::vector<TypedVar *>() /* args */,
@@ -257,6 +259,29 @@
     );
 }
 
+Method *Interface::createGetDescriptorMethod() const {
+    std::vector<TypedVar *> *results = new std::vector<TypedVar *>();
+    results->push_back(new TypedVar("descriptor", new StringType()));
+
+    return new Method("interfaceDescriptor",
+        new std::vector<TypedVar *>() /* args */,
+        results,
+        false /* oneway */,
+        new std::vector<Annotation *>(),
+        HIDL_GET_DESCRIPTOR_TRANSACTION,
+        { { IMPL_HEADER, [this](auto &out) {
+            out << "_hidl_cb("
+                << fullName()
+                << "::descriptor);\n"
+                << "return ::android::hardware::Void();";
+        } } }, /* cppImpl */
+        { { IMPL_HEADER, [this](auto &out) {
+            out << "return "
+                << fullJavaName()
+                << ".kInterfaceName;\n";
+         } } } /* javaImpl */
+    );
+}
 
 bool Interface::addMethod(Method *method) {
     if (isIBase()) {
diff --git a/Interface.h b/Interface.h
index 87a50bc..5cba6c4 100644
--- a/Interface.h
+++ b/Interface.h
@@ -114,6 +114,7 @@
     std::vector<Method *> mReservedMethods;
     mutable bool mIsJavaCompatibleInProgress;
     Method *createDescriptorChainMethod() const;
+    Method *createGetDescriptorMethod() const;
     Method *createSyspropsChangedMethod() const;
     Method *createLinkToDeathMethod() const;
     Method *createUnlinkToDeathMethod() const;
diff --git a/test/java_test/hidl_test_java_native.cpp b/test/java_test/hidl_test_java_native.cpp
index 6b276bf..63909c8 100644
--- a/test/java_test/hidl_test_java_native.cpp
+++ b/test/java_test/hidl_test_java_native.cpp
@@ -636,6 +636,12 @@
     EXPECT_TRUE(ret.isOk());
 }
 
+TEST_F(HidlTest, GetDescriptorTest) {
+    EXPECT_OK(baz->interfaceDescriptor([&] (const auto &desc) {
+        EXPECT_EQ(desc, IBaz::descriptor);
+    }));
+}
+
 TEST_F(HidlTest, BazSomeBaseMethodTest) {
     EXPECT_OK(baz->someBaseMethod());
 }
diff --git a/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java b/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
index f5fd258..78594c3 100644
--- a/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
+++ b/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
@@ -449,6 +449,10 @@
         proxy.someBaseMethod();
 
         {
+            Expect(proxy.interfaceDescriptor(), IBaz.kInterfaceName);
+        }
+
+        {
             IBase.Foo foo = new IBase.Foo();
             foo.x = 1;
 
diff --git a/test/main.cpp b/test/main.cpp
index cbf3d6f..cc6a2df 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -740,6 +740,14 @@
     }));
 }
 
+TEST_F(HidlTest, FooGetDescriptorTest) {
+    EXPECT_OK(foo->interfaceDescriptor([&] (const auto &desc) {
+        EXPECT_EQ(desc, gMode == BINDERIZED
+                ? IBar::descriptor // service is actually IBar in binderized mode
+                : IFoo::descriptor); // dlopened, so service is IFoo
+    }));
+}
+
 TEST_F(HidlTest, FooDoThisTest) {
     ALOGI("CLIENT call doThis.");
     EXPECT_OK(foo->doThis(1.0f));