Merge "Fix IHwBinder.asInterface(...) to respect the interfaceChain and return null"
diff --git a/generateJava.cpp b/generateJava.cpp
index 6e5d91b..2db078d 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -160,7 +160,7 @@
         << ifaceName
         << "\";\n\n";
 
-    out << "public static "
+    out << "/* package private */ static "
         << ifaceName
         << " asInterface(android.os.IHwBinder binder) {\n";
 
@@ -188,7 +188,37 @@
     out.unindent();
     out << "}\n\n";
 
-    out << "return new " << ifaceName << ".Proxy(binder);\n";
+    out << ifaceName << " proxy = new " << ifaceName << ".Proxy(binder);\n\n";
+    out << "try {\n";
+    out.indent();
+    out << "for (String descriptor : proxy.interfaceChain()) {\n";
+    out.indent();
+    out << "if (descriptor.equals(kInterfaceName)) {\n";
+    out.indent();
+    out << "return proxy;\n";
+    out.unindent();
+    out << "}\n";
+    out.unindent();
+    out << "}\n";
+    out.unindent();
+    out << "} catch (android.os.RemoteException e) {\n";
+    out.indent();
+    out.unindent();
+    out << "}\n\n";
+
+    out << "return null;\n";
+
+    out.unindent();
+    out << "}\n\n";
+
+    out << "public static "
+        << ifaceName
+        << " castFrom(android.os.IHwInterface iface) {\n";
+    out.indent();
+
+    out << "return (iface == null) ? null : "
+        << ifaceName
+        << ".asInterface(iface.asBinder());\n";
 
     out.unindent();
     out << "}\n\n";
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 87c4676..1d9ef54 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
@@ -18,6 +18,7 @@
 
 import android.hardware.tests.baz.V1_0.IBase;
 import android.hardware.tests.baz.V1_0.IBaz;
+import android.hardware.tests.baz.V1_0.IQuux;
 import android.hardware.tests.baz.V1_0.IBaz.NestedStruct;
 import android.hardware.tests.baz.V1_0.IBazCallback;
 import android.os.HwBinder;
@@ -237,6 +238,14 @@
             // Test access through base interface binder.
             IBase baseProxy = IBase.getService("baz");
             baseProxy.someBaseMethod();
+
+            IBaz bazProxy = IBaz.castFrom(baseProxy);
+            ExpectTrue(bazProxy != null);
+
+            // IQuux is completely unrelated to IBase/IBaz, so the following
+            // should fail, i.e. return null.
+            IQuux quuxProxy = IQuux.castFrom(baseProxy);
+            ExpectTrue(quuxProxy == null);
         }
 
         IBaz proxy = IBaz.getService("baz");