Merge "GTest test-cases for HIDL safe unions in Java"
diff --git a/test/java_test/Android.bp b/test/java_test/Android.bp
index d89c3d4..4f18adf 100644
--- a/test/java_test/Android.bp
+++ b/test/java_test/Android.bp
@@ -21,6 +21,7 @@
         "android.hardware.tests.baz@1.0",
         "android.hardware.tests.expression@1.0",
         "android.hardware.tests.inheritance@1.0",
+        "android.hardware.tests.safeunion@1.0",
     ],
 
     // impls should never be static, these are used only for testing purposes
@@ -28,6 +29,7 @@
     // implementations
     whole_static_libs: [
         "android.hardware.tests.baz@1.0-impl",
+        "android.hardware.tests.safeunion@1.0-impl",
     ],
 
     compile_multilib: "both",
@@ -42,5 +44,6 @@
         "android.hardware.tests.baz-V1.0-java",
         "android.hardware.tests.expression-V1.0-java",
         "android.hardware.tests.inheritance-V1.0-java",
+        "android.hardware.tests.safeunion-V1.0-java",
     ],
 }
diff --git a/test/java_test/hidl_test_java_native.cpp b/test/java_test/hidl_test_java_native.cpp
index d155e09..5e26d31 100644
--- a/test/java_test/hidl_test_java_native.cpp
+++ b/test/java_test/hidl_test_java_native.cpp
@@ -20,6 +20,8 @@
 #include <android-base/logging.h>
 
 #include <android/hardware/tests/baz/1.0/IBaz.h>
+#include <android/hardware/tests/safeunion/1.0/IOtherInterface.h>
+#include <android/hardware/tests/safeunion/1.0/ISafeUnion.h>
 
 #include <hidl/LegacySupport.h>
 #include <hidl/ServiceManagement.h>
@@ -31,6 +33,8 @@
 using ::android::hardware::tests::baz::V1_0::IBase;
 using ::android::hardware::tests::baz::V1_0::IBaz;
 using ::android::hardware::tests::baz::V1_0::IBazCallback;
+using ::android::hardware::tests::safeunion::V1_0::IOtherInterface;
+using ::android::hardware::tests::safeunion::V1_0::ISafeUnion;
 
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_vec;
@@ -39,6 +43,10 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 
+using InterfaceTypeSafeUnion = ISafeUnion::InterfaceTypeSafeUnion;
+using LargeSafeUnion = ISafeUnion::LargeSafeUnion;
+using SmallSafeUnion = ISafeUnion::SmallSafeUnion;
+
 struct BazCallback : public IBazCallback {
     Return<void> heyItsMe(const sp<IBazCallback> &cb) override;
     Return<void> hey() override;
@@ -57,6 +65,16 @@
     return Void();
 }
 
+struct OtherInterface : public IOtherInterface {
+    Return<void> concatTwoStrings(const hidl_string& a, const hidl_string& b,
+                                  concatTwoStrings_cb _hidl_cb) override {
+        hidl_string result = std::string(a) + std::string(b);
+        _hidl_cb(result);
+
+        return Void();
+    }
+};
+
 using std::to_string;
 
 static void usage(const char *me) {
@@ -73,17 +91,26 @@
 
 struct HidlTest : public ::testing::Test {
     sp<IBaz> baz;
+    sp<ISafeUnion> safeunionInterface;
+    sp<IOtherInterface> otherInterface;
 
     void SetUp() override {
         using namespace ::android::hardware;
 
-        ::android::hardware::details::waitForHwService(
-                IBaz::descriptor, "baz");
-
-        baz = IBaz::getService("baz");
-
-        CHECK(baz != NULL);
+        ::android::hardware::details::waitForHwService(IBaz::descriptor, "default");
+        baz = IBaz::getService();
+        CHECK(baz != nullptr);
         CHECK(baz->isRemote());
+
+        ::android::hardware::details::waitForHwService(ISafeUnion::descriptor, "default");
+        safeunionInterface = ISafeUnion::getService();
+        CHECK(safeunionInterface != nullptr);
+        CHECK(safeunionInterface->isRemote());
+
+        ::android::hardware::details::waitForHwService(IOtherInterface::descriptor, "default");
+        otherInterface = IOtherInterface::getService();
+        CHECK(otherInterface != nullptr);
+        CHECK(otherInterface->isRemote());
     }
 
     void TearDown() override {
@@ -574,6 +601,149 @@
                 in, [&](const auto &out) { EXPECT_EQ(in, out); }));
 }
 
+TEST_F(HidlTest, SafeUnionNoInitTest) {
+    EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+        EXPECT_EQ(LargeSafeUnion::hidl_discriminator::hidl_no_init, safeUnion.getDiscriminator());
+    }));
+}
+
+TEST_F(HidlTest, SafeUnionSimpleTest) {
+    EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+        EXPECT_OK(safeunionInterface->setA(safeUnion, -5, [&](const LargeSafeUnion& safeUnion) {
+            EXPECT_EQ(LargeSafeUnion::hidl_discriminator::a, safeUnion.getDiscriminator());
+            EXPECT_EQ(-5, safeUnion.a());
+
+            uint64_t max = std::numeric_limits<uint64_t>::max();
+            EXPECT_OK(
+                safeunionInterface->setD(safeUnion, max, [&](const LargeSafeUnion& safeUnion) {
+                    EXPECT_EQ(LargeSafeUnion::hidl_discriminator::d, safeUnion.getDiscriminator());
+                    EXPECT_EQ(max, safeUnion.d());
+                }));
+        }));
+    }));
+}
+
+TEST_F(HidlTest, SafeUnionArrayLikeTypesTest) {
+    const std::array<int64_t, 5> testArray{1, -2, 3, -4, 5};
+    const hidl_vec<uint64_t> testVector{std::numeric_limits<uint64_t>::max()};
+
+    EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+        EXPECT_OK(
+            safeunionInterface->setF(safeUnion, testArray, [&](const LargeSafeUnion& safeUnion) {
+                EXPECT_EQ(LargeSafeUnion::hidl_discriminator::f, safeUnion.getDiscriminator());
+
+                for (size_t i = 0; i < testArray.size(); i++) {
+                    EXPECT_EQ(testArray[i], safeUnion.f()[i]);
+                }
+            }));
+
+        EXPECT_OK(
+            safeunionInterface->setI(safeUnion, testVector, [&](const LargeSafeUnion& safeUnion) {
+                EXPECT_EQ(LargeSafeUnion::hidl_discriminator::i, safeUnion.getDiscriminator());
+                EXPECT_EQ(testVector, safeUnion.i());
+            }));
+    }));
+}
+
+TEST_F(HidlTest, SafeUnionStringTypeTest) {
+    const std::string testString =
+        "This is an inordinately long test string to exercise hidl_string types in safe unions.";
+
+    EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+        EXPECT_OK(safeunionInterface->setG(
+            safeUnion, hidl_string(testString), [&](const LargeSafeUnion& safeUnion) {
+                EXPECT_EQ(LargeSafeUnion::hidl_discriminator::g, safeUnion.getDiscriminator());
+                EXPECT_EQ(testString, std::string(safeUnion.g()));
+            }));
+    }));
+}
+
+TEST_F(HidlTest, SafeUnionNestedTest) {
+    SmallSafeUnion smallSafeUnion;
+    smallSafeUnion.a(1);
+
+    EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+        EXPECT_OK(safeunionInterface->setL(
+            safeUnion, smallSafeUnion, [&](const LargeSafeUnion& safeUnion) {
+                EXPECT_EQ(LargeSafeUnion::hidl_discriminator::l, safeUnion.getDiscriminator());
+
+                EXPECT_EQ(SmallSafeUnion::hidl_discriminator::a, safeUnion.l().getDiscriminator());
+                EXPECT_EQ(1, safeUnion.l().a());
+            }));
+    }));
+}
+
+TEST_F(HidlTest, SafeUnionInterfaceTest) {
+    const std::array<int8_t, 7> testArray{-1, -2, -3, 0, 1, 2, 3};
+    const std::string testStringA = "Hello";
+    const std::string testStringB = "World";
+
+    EXPECT_OK(
+        safeunionInterface->newInterfaceTypeSafeUnion([&](const InterfaceTypeSafeUnion& safeUnion) {
+            EXPECT_EQ(InterfaceTypeSafeUnion::hidl_discriminator::hidl_no_init,
+                      safeUnion.getDiscriminator());
+
+            EXPECT_OK(safeunionInterface->setInterfaceB(
+                safeUnion, testArray, [&](const InterfaceTypeSafeUnion& safeUnion) {
+                    EXPECT_EQ(InterfaceTypeSafeUnion::hidl_discriminator::b,
+                              safeUnion.getDiscriminator());
+
+                    for (size_t i = 0; i < testArray.size(); i++) {
+                        EXPECT_EQ(testArray[i], safeUnion.b()[i]);
+                    }
+                }));
+        }));
+
+    // Same-process interface calls are not supported in Java, so we use
+    // a safe_union instance bound to this (client) process instead of
+    // safeunionInterface to exercise this test-case. Ref: b/110957763.
+    InterfaceTypeSafeUnion safeUnion;
+    safeUnion.c(otherInterface);
+
+    EXPECT_EQ(InterfaceTypeSafeUnion::hidl_discriminator::c, safeUnion.getDiscriminator());
+    EXPECT_OK(safeUnion.c()->concatTwoStrings(
+        hidl_string(testStringA), hidl_string(testStringB), [&](const hidl_string& result) {
+            EXPECT_EQ(testStringA + testStringB, std::string(result));
+        }));
+}
+
+TEST_F(HidlTest, SafeUnionEqualityTest) {
+    EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& one) {
+        EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+            EXPECT_FALSE(one == two);
+            EXPECT_TRUE(one != two);
+        }));
+
+        EXPECT_OK(safeunionInterface->setA(one, 1, [&](const LargeSafeUnion& one) {
+            EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+                EXPECT_FALSE(one == two);
+                EXPECT_TRUE(one != two);
+            }));
+
+            EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+                EXPECT_OK(safeunionInterface->setB(two, 1, [&](const LargeSafeUnion& two) {
+                    EXPECT_FALSE(one == two);
+                    EXPECT_TRUE(one != two);
+                }));
+            }));
+
+            EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+                EXPECT_OK(safeunionInterface->setA(two, 2, [&](const LargeSafeUnion& two) {
+                    EXPECT_FALSE(one == two);
+                    EXPECT_TRUE(one != two);
+                }));
+            }));
+
+            EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+                EXPECT_OK(safeunionInterface->setA(two, 1, [&](const LargeSafeUnion& two) {
+                    EXPECT_TRUE(one == two);
+                    EXPECT_FALSE(one != two);
+                }));
+            }));
+        }));
+    }));
+}
+
 int main(int argc, char **argv) {
     setenv("TREBLE_TESTING_OVERRIDE", "true", true);
 
@@ -622,6 +792,19 @@
         return status;
     }
 
-    return defaultPassthroughServiceImplementation<IBaz>("baz");
+    ::android::status_t status;
+    configureRpcThreadpool(1, true);
 
+    status = registerPassthroughServiceImplementation<IBaz>();
+    CHECK(status == ::android::OK) << "IBaz didn't register";
+
+    status = registerPassthroughServiceImplementation<ISafeUnion>();
+    CHECK(status == ::android::OK) << "ISafeUnion didn't register";
+
+    sp<IOtherInterface> otherInterface = new OtherInterface();
+    status = otherInterface->registerAsService();
+    CHECK(status == ::android::OK) << "IOtherInterface didn't register";
+
+    joinRpcThreadpool();
+    return 0;
 }
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 f670732..1d71446 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
@@ -22,6 +22,11 @@
 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.hardware.tests.safeunion.V1_0.IOtherInterface;
+import android.hardware.tests.safeunion.V1_0.ISafeUnion;
+import android.hardware.tests.safeunion.V1_0.ISafeUnion.InterfaceTypeSafeUnion;
+import android.hardware.tests.safeunion.V1_0.ISafeUnion.LargeSafeUnion;
+import android.hardware.tests.safeunion.V1_0.ISafeUnion.SmallSafeUnion;
 import android.os.HwBinder;
 import android.os.RemoteException;
 import android.os.HidlSupport;
@@ -214,6 +219,130 @@
         ExpectTrue(!HidlSupport.deepEquals(l, r));
     }
 
+    private void runClientSafeUnionTests() throws RemoteException {
+        ISafeUnion safeunionInterface = ISafeUnion.getService();
+
+        {
+            // SafeUnionNoInitTest
+            LargeSafeUnion safeUnion = safeunionInterface.newLargeSafeUnion();
+            ExpectTrue(
+                safeUnion.getDiscriminator() == LargeSafeUnion.hidl_discriminator.hidl_no_init);
+        }
+        {
+            // SafeUnionSimpleTest
+            LargeSafeUnion safeUnion = safeunionInterface.newLargeSafeUnion();
+
+            safeUnion = safeunionInterface.setA(safeUnion, (byte) -5);
+            ExpectTrue(safeUnion.getDiscriminator() == LargeSafeUnion.hidl_discriminator.a);
+            ExpectTrue(safeUnion.a() == (byte) -5);
+
+            safeUnion = safeunionInterface.setD(safeUnion, Long.MAX_VALUE);
+            ExpectTrue(safeUnion.getDiscriminator() == LargeSafeUnion.hidl_discriminator.d);
+            ExpectTrue(safeUnion.d() == Long.MAX_VALUE);
+        }
+        {
+            // SafeUnionArrayLikeTypesTest
+            long[] testArray = new long[] {1, -2, 3, -4, 5};
+            ArrayList<Long> testVector = new ArrayList<Long>(Arrays.asList(Long.MAX_VALUE));
+
+            LargeSafeUnion safeUnion = safeunionInterface.newLargeSafeUnion();
+            safeUnion = safeunionInterface.setF(safeUnion, testArray);
+            ExpectTrue(safeUnion.getDiscriminator() == LargeSafeUnion.hidl_discriminator.f);
+            ExpectDeepEq(testArray, safeUnion.f());
+
+            safeUnion = safeunionInterface.newLargeSafeUnion();
+            safeUnion = safeunionInterface.setI(safeUnion, testVector);
+            ExpectTrue(safeUnion.getDiscriminator() == LargeSafeUnion.hidl_discriminator.i);
+            ExpectDeepEq(testVector, safeUnion.i());
+        }
+        {
+            // SafeUnionStringTypeTest
+            String testString = "This is an inordinately long test string.";
+
+            LargeSafeUnion safeUnion = safeunionInterface.newLargeSafeUnion();
+            safeUnion = safeunionInterface.setG(safeUnion, testString);
+            ExpectTrue(safeUnion.getDiscriminator() == LargeSafeUnion.hidl_discriminator.g);
+            ExpectDeepEq(testString, safeUnion.g());
+        }
+        {
+            // SafeUnionNestedTest
+            SmallSafeUnion smallSafeUnion = new SmallSafeUnion();
+            smallSafeUnion.a((byte) 1);
+
+            LargeSafeUnion safeUnion = safeunionInterface.newLargeSafeUnion();
+            safeUnion = safeunionInterface.setL(safeUnion, smallSafeUnion);
+            ExpectTrue(safeUnion.getDiscriminator() == LargeSafeUnion.hidl_discriminator.l);
+            ExpectTrue(safeUnion.l().getDiscriminator() == SmallSafeUnion.hidl_discriminator.a);
+            ExpectTrue(safeUnion.l().a() == (byte) 1);
+        }
+        {
+            // SafeUnionInterfaceTest
+            byte[] testArray = new byte[] {-1, -2, -3, 0, 1, 2, 3};
+            String testStringA = "Hello";
+            String testStringB = "World";
+
+            IOtherInterface otherInterface = IOtherInterface.getService();
+
+            InterfaceTypeSafeUnion safeUnion = safeunionInterface.newInterfaceTypeSafeUnion();
+            safeUnion = safeunionInterface.setInterfaceB(safeUnion, testArray);
+            ExpectTrue(safeUnion.getDiscriminator() == InterfaceTypeSafeUnion.hidl_discriminator.b);
+            ExpectDeepEq(testArray, safeUnion.b());
+
+            safeUnion.c(otherInterface);
+            ExpectTrue(safeUnion.getDiscriminator() == InterfaceTypeSafeUnion.hidl_discriminator.c);
+            String result = safeUnion.c().concatTwoStrings(testStringA, testStringB);
+            Expect(result, testStringA + testStringB);
+        }
+        {
+            // SafeUnionEqualityTest
+            LargeSafeUnion one = safeunionInterface.newLargeSafeUnion();
+            LargeSafeUnion two = safeunionInterface.newLargeSafeUnion();
+            ExpectFalse(one.equals(two));
+
+            one = safeunionInterface.setA(one, (byte) 1);
+            ExpectFalse(one.equals(two));
+
+            two = safeunionInterface.setB(two, (byte) 1);
+            ExpectFalse(one.equals(two));
+
+            two = safeunionInterface.setA(two, (byte) 2);
+            ExpectFalse(one.equals(two));
+
+            two = safeunionInterface.setA(two, (byte) 1);
+            ExpectTrue(one.equals(two));
+        }
+        {
+            // SafeUnionDeepEqualityTest
+            ArrayList<Long> testVectorA = new ArrayList(Arrays.asList(1L, 2L, 3L));
+            ArrayList<Long> testVectorB = new ArrayList(Arrays.asList(2L, 1L, 3L));
+
+            LargeSafeUnion one = safeunionInterface.newLargeSafeUnion();
+            LargeSafeUnion two = safeunionInterface.newLargeSafeUnion();
+
+            one = safeunionInterface.setI(one, testVectorA);
+            two = safeunionInterface.setI(two, testVectorB);
+            ExpectFalse(one.equals(two));
+
+            two = safeunionInterface.setI(two, (ArrayList<Long>) testVectorA.clone());
+            ExpectTrue(one.equals(two));
+        }
+        {
+            // SafeUnionHashCodeTest
+            ArrayList<Boolean> testVector =
+                new ArrayList(Arrays.asList(true, false, false, true, true));
+
+            LargeSafeUnion one = safeunionInterface.newLargeSafeUnion();
+            LargeSafeUnion two = safeunionInterface.newLargeSafeUnion();
+
+            one = safeunionInterface.setH(one, testVector);
+            two = safeunionInterface.setA(two, (byte) -5);
+            ExpectFalse(one.hashCode() == two.hashCode());
+
+            two = safeunionInterface.setH(two, (ArrayList<Boolean>) testVector.clone());
+            ExpectTrue(one.hashCode() == two.hashCode());
+        }
+    }
+
     private void client() throws RemoteException {
 
         ExpectDeepEq(null, null);
@@ -271,7 +400,7 @@
 
         {
             // Test access through base interface binder.
-            IBase baseProxy = IBase.getService("baz");
+            IBase baseProxy = IBase.getService();
             baseProxy.someBaseMethod();
 
             IBaz bazProxy = IBaz.castFrom(baseProxy);
@@ -285,13 +414,13 @@
 
         {
             // Test waiting API
-            IBase baseProxyA = IBaz.getService("baz", true /* retry */);
+            IBase baseProxyA = IBaz.getService(true /* retry */);
             ExpectTrue(baseProxyA != null);
-            IBase baseProxyB = IBaz.getService("baz", false /* retry */);
+            IBase baseProxyB = IBaz.getService(false /* retry */);
             ExpectTrue(baseProxyB != null);
         }
 
-        IBaz proxy = IBaz.getService("baz");
+        IBaz proxy = IBaz.getService();
 
         proxy.ping();
 
@@ -757,9 +886,9 @@
             // testProxyEquals
             // TODO(b/68727931): test passthrough services as well.
 
-            IBase proxy1 = IBase.getService("baz");
-            IBase proxy2 = IBase.getService("baz");
-            IBaz proxy3 = IBaz.getService("baz");
+            IBase proxy1 = IBase.getService();
+            IBase proxy2 = IBase.getService();
+            IBaz proxy3 = IBaz.getService();
             IBazCallback callback1 = new BazCallback();
             IBazCallback callback2 = new BazCallback();
             IServiceManager manager = IServiceManager.getService();
@@ -789,7 +918,7 @@
             ExpectFalse(set.contains(manager));
         }
         {
-            IBaz baz = IBaz.getService("baz");
+            IBaz baz = IBaz.getService();
             ExpectTrue(baz != null);
             IBaz.StructWithInterface swi = new IBaz.StructWithInterface();
             swi.dummy = baz;
@@ -801,6 +930,8 @@
             ExpectTrue(swi_back.number == 12345678);
         }
 
+        runClientSafeUnionTests();
+
         // --- DEATH RECIPIENT TESTING ---
         // This must always be done last, since it will kill the native server process
         HidlDeathRecipient recipient1 = new HidlDeathRecipient();
@@ -1087,11 +1218,160 @@
         }
     }
 
+    class SafeUnion extends ISafeUnion.Stub {
+        @Override
+        public LargeSafeUnion newLargeSafeUnion() {
+            Log.d(TAG, "SERVER: newLargeSafeUnion");
+            return new LargeSafeUnion();
+        }
+
+        @Override
+        public LargeSafeUnion setA(LargeSafeUnion safeUnion, byte a) {
+            Log.d(TAG, "SERVER: setA(" + a + ")");
+            safeUnion.a(a);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setB(LargeSafeUnion safeUnion, short b) {
+            Log.d(TAG, "SERVER: setB(" + b + ")");
+            safeUnion.b(b);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setC(LargeSafeUnion safeUnion, int c) {
+            Log.d(TAG, "SERVER: setC(" + c + ")");
+            safeUnion.c(c);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setD(LargeSafeUnion safeUnion, long d) {
+            Log.d(TAG, "SERVER: setD(" + d + ")");
+            safeUnion.d(d);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setE(LargeSafeUnion safeUnion, byte[/* 13 */] e) {
+            Log.d(TAG, "SERVER: setE(" + e + ")");
+            safeUnion.e(e);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setF(LargeSafeUnion safeUnion, long[/* 5 */] f) {
+            Log.d(TAG, "SERVER: setF(" + f + ")");
+            safeUnion.f(f);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setG(LargeSafeUnion safeUnion, String g) {
+            Log.d(TAG, "SERVER: setG(" + g + ")");
+            safeUnion.g(g);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setH(LargeSafeUnion safeUnion, ArrayList<Boolean> h) {
+            Log.d(TAG, "SERVER: setH(" + h + ")");
+            safeUnion.h(h);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setI(LargeSafeUnion safeUnion, ArrayList<Long> i) {
+            Log.d(TAG, "SERVER: setI(" + i + ")");
+            safeUnion.i(i);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setJ(LargeSafeUnion safeUnion, ISafeUnion.J j) {
+            Log.d(TAG, "SERVER: setJ(" + j + ")");
+            safeUnion.j(j);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setK(LargeSafeUnion safeUnion, LargeSafeUnion.K k) {
+            Log.d(TAG, "SERVER: setK(" + k + ")");
+            safeUnion.k(k);
+
+            return safeUnion;
+        }
+
+        @Override
+        public LargeSafeUnion setL(LargeSafeUnion safeUnion, SmallSafeUnion l) {
+            Log.d(TAG, "SERVER: setL(" + l + ")");
+            safeUnion.l(l);
+
+            return safeUnion;
+        }
+
+        @Override
+        public InterfaceTypeSafeUnion newInterfaceTypeSafeUnion() {
+            Log.d(TAG, "SERVER: newInterfaceTypeSafeUnion");
+            return new InterfaceTypeSafeUnion();
+        }
+
+        @Override
+        public InterfaceTypeSafeUnion setInterfaceA(InterfaceTypeSafeUnion safeUnion, int a) {
+            Log.d(TAG, "SERVER: setInterfaceA(" + a + ")");
+            safeUnion.a(a);
+
+            return safeUnion;
+        }
+
+        @Override
+        public InterfaceTypeSafeUnion setInterfaceB(
+            InterfaceTypeSafeUnion safeUnion, byte[/* 7 */] b) {
+            Log.d(TAG, "SERVER: setInterfaceB(" + b + ")");
+            safeUnion.b(b);
+
+            return safeUnion;
+        }
+
+        @Override
+        public InterfaceTypeSafeUnion setInterfaceC(
+            InterfaceTypeSafeUnion safeUnion, IOtherInterface c) {
+            Log.d(TAG, "SERVER: setInterfaceC(" + c + ")");
+            safeUnion.c(c);
+
+            return safeUnion;
+        }
+    }
+
+    class OtherInterface extends IOtherInterface.Stub {
+        @Override
+        public String concatTwoStrings(String a, String b) {
+            return a.concat(b);
+        }
+    }
+
     private void server() throws RemoteException {
         HwBinder.configureRpcThreadpool(1, true);
 
         Baz baz = new Baz();
-        baz.registerAsService("baz");
+        baz.registerAsService("default");
+
+        SafeUnion safeunionInterface = new SafeUnion();
+        safeunionInterface.registerAsService("default");
+
+        OtherInterface otherInterface = new OtherInterface();
+        otherInterface.registerAsService("default");
 
         HwBinder.joinRpcThreadpool();
     }