Merge "Use the new "Bool*" accessor methods for booleans instead of treating them like"
diff --git a/EnumType.cpp b/EnumType.cpp
index 3f9b3dd..843a946 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -1,6 +1,7 @@
 #include "EnumType.h"
 
 #include "Formatter.h"
+#include <inttypes.h>
 #include "ScalarType.h"
 
 #include <android-base/logging.h>
@@ -127,7 +128,7 @@
             sprintf(out, "%d", (int)(int32_t)x);
         } else {
             assert(typeName == "long");
-            sprintf(out, "%lldL", (int64_t)x);
+            sprintf(out, "%" PRId64 "L", (int64_t)x);
         }
 
         *output = out;
diff --git a/main.cpp b/main.cpp
index d691916..59a842e 100644
--- a/main.cpp
+++ b/main.cpp
@@ -207,6 +207,12 @@
     out << "\n";
     out.unindent();
 
+    if (path.find("hardware/interfaces/tests/") != std::string::npos) {
+        out << "\nLOCAL_COMPATIBILITY_SUITE := vts"
+            << "\n-include test/vts/tools/build/Android.packaging_sharedlib.mk";
+        // TODO(yim): b/30589200 remove the above -include line after the
+        // build rule change is merged.
+    }
     out << "\ninclude $(BUILD_SHARED_LIBRARY)\n";
 
     return OK;
diff --git a/test/Android.mk b/test/Android.mk
index aca4915..7cee786 100644
--- a/test/Android.mk
+++ b/test/Android.mk
@@ -7,6 +7,9 @@
 LOCAL_SRC_FILES :=                                  \
     main.cpp                                        \
 
+LOCAL_C_INCLUDES := \
+    external/gtest/include
+
 LOCAL_SHARED_LIBRARIES :=       	\
     libandroid_runtime          	\
     libbase                     	\
@@ -18,6 +21,9 @@
     android.hardware.tests.foo@1.0	\
     android.hardware.tests.bar@1.0	\
 
+LOCAL_STATIC_LIBRARIES := \
+    libgtest
+
 LOCAL_MODULE_TAGS := samples
 
 LOCAL_CFLAGS := -O0 -g
diff --git a/test/main.cpp b/test/main.cpp
index 918c530..72ec8cd 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -5,11 +5,25 @@
 #include <android/hardware/tests/foo/1.0/BnFooCallback.h>
 #include <android/hardware/tests/bar/1.0/BnBar.h>
 
+#include <gtest/gtest.h>
+#include <inttypes.h>
+#if GTEST_IS_THREADSAFE
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <pthread.h>
+#else
+#error "GTest did not detect pthread library."
+#endif
+
 #include <hidl/IServiceManager.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/ProcessState.h>
 #include <hwbinder/Status.h>
 
+#include <utils/Condition.h>
+#include <utils/Timers.h>
+
 using ::android::hardware::tests::foo::V1_0::BnFoo;
 using ::android::hardware::tests::foo::V1_0::BnFooCallback;
 using ::android::hardware::tests::bar::V1_0::BnBar;
@@ -22,30 +36,89 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::hidl_string;
 using ::android::sp;
+using ::android::Mutex;
+using ::android::Condition;
 
 struct FooCallback : public BnFooCallback {
+    FooCallback() : invokeInfo{}, mLock{}, mCond{} {}
     Status heyItsYou(const sp<IFooCallback> &cb) override;
     Return<bool> heyItsYouIsntIt(const sp<IFooCallback> &cb) override;
     Status heyItsTheMeaningOfLife(uint8_t tmol) override;
+    Status reportResults(int64_t ns, reportResults_cb cb) override;
+    Status youBlockedMeFor(const int64_t ns[3]) override;
+
+    static constexpr nsecs_t DELAY_S = 5;
+    static constexpr nsecs_t DELAY_NS = seconds_to_nanoseconds(DELAY_S);
+    static constexpr nsecs_t TOLERANCE_NS = milliseconds_to_nanoseconds(10);
+    static constexpr nsecs_t ONEWAY_TOLERANCE_NS = milliseconds_to_nanoseconds(1);
+
+    InvokeInfo invokeInfo[3];
+    Mutex mLock;
+    Condition mCond;
 };
 
 Status FooCallback::heyItsYou(
         const sp<IFooCallback> &_cb) {
+    nsecs_t start = systemTime();
     ALOGI("SERVER(FooCallback) heyItsYou cb = %p", _cb.get());
+    mLock.lock();
+    invokeInfo[0].invoked = true;
+    invokeInfo[0].timeNs = systemTime() - start;
+    mCond.signal();
+    mLock.unlock();
     return Status::ok();
 }
 
 Return<bool> FooCallback::heyItsYouIsntIt(const sp<IFooCallback> &_cb) {
-    ALOGI("SERVER(FooCallback) heyItsYouIsntIt cb = %p sleeping for 10 seconds", _cb.get());
-    sleep(10);
+    nsecs_t start = systemTime();
+    ALOGI("SERVER(FooCallback) heyItsYouIsntIt cb = %p sleeping for %" PRId64 " seconds", _cb.get(), DELAY_S);
+    sleep(DELAY_S);
     ALOGI("SERVER(FooCallback) heyItsYouIsntIt cb = %p responding", _cb.get());
+    mLock.lock();
+    invokeInfo[1].invoked = true;
+    invokeInfo[1].timeNs = systemTime() - start;
+    mCond.signal();
+    mLock.unlock();
     return true;
 }
 
 Status FooCallback::heyItsTheMeaningOfLife(uint8_t tmol) {
-    ALOGI("SERVER(FooCallback) heyItsTheMeaningOfLife = %d sleeping for 10 seconds", tmol);
-    sleep(10);
+    nsecs_t start = systemTime();
+    ALOGI("SERVER(FooCallback) heyItsTheMeaningOfLife = %d sleeping for %" PRId64 " seconds", tmol, DELAY_S);
+    sleep(DELAY_S);
     ALOGI("SERVER(FooCallback) heyItsTheMeaningOfLife = %d done sleeping", tmol);
+    mLock.lock();
+    invokeInfo[2].invoked = true;
+    invokeInfo[2].timeNs = systemTime() - start;
+    mCond.signal();
+    mLock.unlock();
+    return Status::ok();
+}
+
+Status FooCallback::reportResults(int64_t ns, reportResults_cb cb) {
+    ALOGI("SERVER(FooCallback) reportResults(%" PRId64 ") seconds", nanoseconds_to_seconds(ns));
+    nsecs_t leftToWaitNs = ns;
+    mLock.lock();
+    while (!(invokeInfo[0].invoked && invokeInfo[1].invoked && invokeInfo[2].invoked) &&
+           leftToWaitNs > 0) {
+      nsecs_t start = systemTime();
+      ::android::status_t rc = mCond.waitRelative(mLock, leftToWaitNs);
+      if (rc != ::android::OK) {
+          ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 ") Condition::waitRelative(%" PRId64 ") returned error (%d)", ns, leftToWaitNs, rc);
+          break;
+      }
+      ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 ") Condition::waitRelative was signalled", ns);
+      leftToWaitNs -= systemTime() - start;
+    }
+    mLock.unlock();
+    cb(leftToWaitNs, invokeInfo);
+    return Status::ok();
+}
+
+Status FooCallback::youBlockedMeFor(const int64_t ns[3]) {
+    for (size_t i = 0; i < 3; i++) {
+        invokeInfo[i].callerBlockedNs = ns[i];
+    }
     return Status::ok();
 }
 
@@ -164,14 +237,40 @@
     ALOGI("SERVER(Bar) callMe %p", cb.get());
 
     if (cb != NULL) {
-        ALOGI("SERVER(Bar) callMe %p calling IFooCallback::heyItsYou, should return immediately", cb.get());
+
+        nsecs_t c[3];
+        ALOGI("SERVER(Bar) callMe %p calling IFooCallback::heyItsYou, " \
+              "should return immediately", cb.get());
+        c[0] = systemTime();
         cb->heyItsYou(cb);
-        ALOGI("SERVER(Bar) callMe %p calling IFooCallback::heyItsYouIsntIt, should block for 10 seconds", cb.get());
+        c[0] = systemTime() - c[0];
+        ALOGI("SERVER(Bar) callMe %p calling IFooCallback::heyItsYou " \
+              "returned after %" PRId64 "ns", cb.get(), c[0]);
+
+        ALOGI("SERVER(Bar) callMe %p calling IFooCallback::heyItsYouIsntIt, " \
+              "should block for %" PRId64 " seconds", cb.get(),
+              FooCallback::DELAY_S);
+        c[1] = systemTime();
         bool answer = cb->heyItsYouIsntIt(cb);
-        ALOGI("SERVER(Bar) callMe %p IFooCallback::heyItsYouIsntIt responded with %d", cb.get(), answer);
-        ALOGI("SERVER(Bar) callMe %p calling IFooCallback::heyItsTheMeaningOfLife, should return immediately", cb.get());
+        c[1] = systemTime() - c[1];
+        ALOGI("SERVER(Bar) callMe %p IFooCallback::heyItsYouIsntIt " \
+              "responded with %d after %" PRId64 "ns", cb.get(), answer, c[1]);
+
+        ALOGI("SERVER(Bar) callMe %p calling " \
+              "IFooCallback::heyItsTheMeaningOfLife, " \
+              "should return immediately ", cb.get());
+        c[2] = systemTime();
         cb->heyItsTheMeaningOfLife(42);
-        ALOGI("SERVER(Bar) callMe %p After call to IFooCallback::heyItsTheMeaningOfLife", cb.get());
+        c[2] = systemTime() - c[2];
+        ALOGI("SERVER(Bar) callMe %p After call to " \
+              "IFooCallback::heyItsTheMeaningOfLife " \
+              "responded after %" PRId64 "ns", cb.get(), c[2]);
+
+        ALOGI("SERVER(Bar) callMe %p calling IFooCallback::youBlockedMeFor " \
+              "to report times", cb.get());
+        cb->youBlockedMeFor(c);
+        ALOGI("SERVER(Bar) callMe %p After call to " \
+              "IFooCallback::heyYouBlockedMeFor", cb.get());
     }
 
     return Status::ok();
@@ -264,160 +363,322 @@
     return out;
 }
 
+
 static std::string vecToString(const hidl_vec<int32_t> &vec) {
     return arraylikeToString(vec, vec.size());
 }
 
-static void client() {
+static inline void EXPECT_OK(::android::hardware::Status status) {
+    EXPECT_TRUE(status.isOk());
+}
+
+template<typename T, typename S>
+static inline bool EXPECT_ARRAYEQ(const T arr1, const S arr2, size_t size) {
+    for(size_t i = 0; i < size; i++)
+        if(arr1[i] != arr2[i])
+            return false;
+    return true;
+}
+
+
+template <class T>
+static void startServer(T server, const android::hardware::hidl_version kVersion,
+                        const char *serviceName,
+                        const char *tag) {
     using namespace android::hardware;
     using android::String16;
+    ALOGI("SERVER(%s) registering", tag);
+    defaultServiceManager()->addService(String16(serviceName), server, kVersion);
+    ALOGI("SERVER(%s) starting", tag);
+    ProcessState::self()->setThreadPoolMaxThreadCount(0);
+    ProcessState::self()->startThreadPool();
+    IPCThreadState::self()->joinThreadPool(); // never ends. needs kill().
+    ALOGI("SERVER(%s) ends.", tag);
+}
 
-    const hidl_version kVersion = make_hidl_version(1, 0);
 
-    sp<IBinder> service =
-        defaultServiceManager()->getService(String16("foo"), kVersion);
+class HidlTest : public ::testing::Test {
+public:
+    sp<::android::hardware::IBinder> service;
+    sp<IFoo> foo;
+    sp<IBar> bar;
+    sp<IFooCallback> fooCb;
+    sp<::android::hardware::IBinder> cbService;
+    virtual void SetUp() override {
+        ALOGI("Test setup beginning...");
+        using namespace android::hardware;
+        using android::String16;
+        const hidl_version kVersion = make_hidl_version(1, 0);
 
-    CHECK(service != NULL);
+        service =
+            defaultServiceManager()->getService(String16("foo"), kVersion);
+        ALOGI("CLIENT Found service foo.");
 
-    sp<IFoo> foo = IFoo::asInterface(service);
-    CHECK(foo != NULL);
+        CHECK(service != NULL);
 
+        foo = IFoo::asInterface(service);
+        CHECK(foo != NULL);
+
+        bar = IBar::asInterface(service);
+        CHECK(bar != NULL);
+
+        cbService = defaultServiceManager()->getService(String16("foo callback"), kVersion);
+        CHECK(cbService != NULL);
+
+        fooCb = IFooCallback::asInterface(cbService);
+        CHECK(fooCb != NULL);
+
+        ALOGI("Test setup complete");
+    }
+    virtual void TearDown() override {
+    }
+};
+
+class HidlEnvironment : public ::testing::Environment {
+private:
+    pid_t fooCallbackServerPid, barServerPid;
+public:
+    virtual void SetUp() {
+        ALOGI("Environment setup beginning...");
+        // use fork to create and kill to destroy server processes.
+        if ((barServerPid = fork()) == 0) {
+            // Fear me, I am a child.
+            startServer(new Bar, android::hardware::make_hidl_version(1, 0),
+                "foo", "Bar"); // never returns
+            return;
+        }
+
+        if ((fooCallbackServerPid = fork()) == 0) {
+            // Fear me, I am a second child.
+            startServer(new FooCallback, android::hardware::make_hidl_version(1, 0),
+                "foo callback", "FooCalback"); // never returns
+            return;
+        }
+
+        // Fear you not, I am parent.
+        sleep(1);
+        ALOGI("Environment setup complete.");
+    }
+
+    virtual void TearDown() {
+        // clean up by killing server processes.
+        ALOGI("Environment tear-down beginning...");
+        ALOGI("Killing servers...");
+        if(kill(barServerPid, SIGTERM)) {
+            ALOGE("Could not kill barServer; errno = %d", errno);
+        } else {
+            int status;
+            ALOGI("Waiting for barServer to exit...");
+            waitpid(barServerPid, &status, 0);
+            ALOGI("Continuing...");
+        }
+        if(kill(fooCallbackServerPid, SIGTERM)) {
+            ALOGE("Could not kill fooCallbackServer; errno = %d", errno);
+        } else {
+            int status;
+            ALOGI("Waiting for fooCallbackServer to exit...");
+            waitpid(barServerPid, &status, 0);
+            ALOGI("Continuing...");
+        }
+        ALOGI("Servers all killed.");
+        ALOGI("Environment tear-down complete.");
+    }
+};
+
+TEST_F(HidlTest, FooDoThisTest) {
     ALOGI("CLIENT call doThis.");
-    foo->doThis(1.0f);
+    EXPECT_OK(foo->doThis(1.0f));
     ALOGI("CLIENT doThis returned.");
+    EXPECT_EQ(true, true);
+}
 
+TEST_F(HidlTest, FooDoThatAndReturnSomethingTest) {
     ALOGI("CLIENT call doThatAndReturnSomething.");
     int32_t result = foo->doThatAndReturnSomething(2.0f);
     ALOGI("CLIENT doThatAndReturnSomething returned %d.", result);
+    EXPECT_EQ(result, 666);
+}
 
+TEST_F(HidlTest, FooDoQuiteABitTest) {
     ALOGI("CLIENT call doQuiteABit");
     double something = foo->doQuiteABit(1, 2, 3.0f, 4.0);
     ALOGI("CLIENT doQuiteABit returned %f.", something);
+    EXPECT_DOUBLE_EQ(something, 666.5);
+}
+
+TEST_F(HidlTest, FooDoSomethingElseTest) {
 
     ALOGI("CLIENT call doSomethingElse");
     int32_t param[15];
     for (size_t i = 0; i < sizeof(param) / sizeof(param[0]); ++i) {
         param[i] = i;
     }
-    foo->doSomethingElse(param, [&](const auto &something) {
+    EXPECT_OK(foo->doSomethingElse(param, [&](const auto &something) {
             ALOGI("CLIENT doSomethingElse returned %s.",
                   arraylikeToString(something, 32).c_str());
-        });
+            int32_t expect[] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
+                26, 28, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2};
+            EXPECT_ARRAYEQ(something, expect, 32);
+        }));
+}
 
+TEST_F(HidlTest, FooDoStuffAndReturnAStringTest) {
     ALOGI("CLIENT call doStuffAndReturnAString");
-    foo->doStuffAndReturnAString([&](const auto &something) {
+    EXPECT_OK(foo->doStuffAndReturnAString([&](const auto &something) {
             ALOGI("CLIENT doStuffAndReturnAString returned '%s'.",
                   something.c_str());
-        });
+            EXPECT_STREQ(something.c_str(), "Hello, world");
+        }));
+}
 
+TEST_F(HidlTest, FooMapThisVectorTest) {
     hidl_vec<int32_t> vecParam;
     vecParam.resize(10);
     for (size_t i = 0; i < 10; ++i) {
         vecParam[i] = i;
     }
-    foo->mapThisVector(vecParam, [&](const auto &something) {
+    EXPECT_OK(foo->mapThisVector(vecParam, [&](const auto &something) {
             ALOGI("CLIENT mapThisVector returned %s.",
                   vecToString(something).c_str());
-        });
+            int32_t expect[] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18};
+            EXPECT_ARRAYEQ(something, expect, something.size());
+        }));
+}
 
+TEST_F(HidlTest, FooCallMeTest) {
     ALOGI("CLIENT call callMe.");
-    sp<IBinder> cbService = defaultServiceManager()->getService(String16("foo callback"), kVersion);
-    foo->callMe(IFooCallback::asInterface(cbService));
+    // callMe is oneway, should return instantly.
+    nsecs_t now;
+    now = systemTime();
+    EXPECT_OK(foo->callMe(fooCb));
+    EXPECT_TRUE(systemTime() - now < FooCallback::ONEWAY_TOLERANCE_NS);
     ALOGI("CLIENT callMe returned.");
+}
 
-    ALOGI("CLIENT call userAnEnum.");
+TEST_F(HidlTest, ForReportResultsTest) {
+
+    // Bar::callMe will invoke three methods on FooCallback; one will return
+    // right away (even though it is a two-way method); the second one will
+    // block Bar for FooCallback::DELAY_S seconds, and the third one will return
+    // to Bar right away (is oneway) but will itself block for DELAY_S seconds.
+    // We need a way to make sure that these three things have happened within
+    // 2*DELAY_S seconds plus some small tolerance.
+    //
+    // Method FooCallback::reportResults() takes a timeout parameter.  It blocks for
+    // that length of time, while waiting for the three methods above to
+    // complete.  It returns the information of whether each method was invoked,
+    // as well as how long the body of the method took to execute.  We verify
+    // the information returned by reportResults() against the timeout we pass (which
+    // is long enough for the method bodies to execute, plus tolerance), and
+    // verify that eachof them executed, as expected, and took the length of
+    // time to execute that we also expect.
+
+    const nsecs_t reportResultsNs =
+          seconds_to_nanoseconds(2*(FooCallback::DELAY_S +
+                                    FooCallback::TOLERANCE_NS));
+    ALOGI("CLIENT: Waiting for up to %" PRId64 " seconds.",
+          nanoseconds_to_seconds(reportResultsNs));
+
+    fooCb->reportResults(reportResultsNs,
+                [&](int64_t timeLeftNs,
+                    const IFooCallback::InvokeInfo invokeResults[3]) {
+        ALOGI("CLIENT: FooCallback::reportResults() is returning data.");
+        ALOGI("CLIENT: Waited for %" PRId64 " milliseconds.",
+              nanoseconds_to_milliseconds(reportResultsNs - timeLeftNs));
+
+        EXPECT_TRUE(0 <= timeLeftNs && timeLeftNs <= reportResultsNs);
+
+        // two-way method, was supposed to return right away
+        EXPECT_TRUE(invokeResults[0].invoked);
+        EXPECT_TRUE(invokeResults[0].timeNs <= invokeResults[0].callerBlockedNs);
+        EXPECT_TRUE(invokeResults[0].callerBlockedNs <= FooCallback::TOLERANCE_NS);
+        // two-way method, was supposed to block caller for DELAY_NS
+        EXPECT_TRUE(invokeResults[1].invoked);
+        EXPECT_TRUE(invokeResults[1].timeNs <= invokeResults[1].callerBlockedNs);
+        EXPECT_TRUE(invokeResults[1].callerBlockedNs <=
+                    FooCallback::DELAY_NS + FooCallback::TOLERANCE_NS);
+        // one-way method, do not block caller, but body was supposed to block for DELAY_NS
+        EXPECT_TRUE(invokeResults[2].invoked);
+        EXPECT_TRUE(invokeResults[2].callerBlockedNs <= FooCallback::ONEWAY_TOLERANCE_NS);
+        EXPECT_TRUE(invokeResults[2].timeNs <= FooCallback::DELAY_NS + FooCallback::TOLERANCE_NS);
+    });
+}
+
+
+
+TEST_F(HidlTest, FooUseAnEnumTest) {
+    ALOGI("CLIENT call useAnEnum.");
     IFoo::SomeEnum sleepy = foo->useAnEnum(IFoo::SomeEnum::quux);
     ALOGI("CLIENT useAnEnum returned %u", (unsigned)sleepy);
+    EXPECT_EQ(sleepy, IFoo::SomeEnum::goober);
+}
 
+TEST_F(HidlTest, FooHaveAGooberTest) {
     hidl_vec<IFoo::Goober> gooberVecParam;
     gooberVecParam.resize(2);
     gooberVecParam[0].name = "Hello";
     gooberVecParam[1].name = "World";
 
     ALOGI("CLIENT call haveAGooberVec.");
-    foo->haveAGooberVec(gooberVecParam);
+    EXPECT_OK(foo->haveAGooberVec(gooberVecParam));
     ALOGI("CLIENT haveAGooberVec returned.");
 
     ALOGI("CLIENT call haveaGoober.");
-    foo->haveAGoober(gooberVecParam[0]);
+    EXPECT_OK(foo->haveAGoober(gooberVecParam[0]));
     ALOGI("CLIENT haveaGoober returned.");
 
     ALOGI("CLIENT call haveAGooberArray.");
     IFoo::Goober gooberArrayParam[20];
-    foo->haveAGooberArray(gooberArrayParam);
+    EXPECT_OK(foo->haveAGooberArray(gooberArrayParam));
     ALOGI("CLIENT haveAGooberArray returned.");
+}
 
+TEST_F(HidlTest, FooHaveATypeFromAnotherFileTest) {
     ALOGI("CLIENT call haveATypeFromAnotherFile.");
     Abc abcParam{};
     abcParam.x = "alphabet";
     abcParam.y = 3.14f;
     abcParam.z = new native_handle_t();
-    foo->haveATypeFromAnotherFile(abcParam);
+    EXPECT_OK(foo->haveATypeFromAnotherFile(abcParam));
     ALOGI("CLIENT haveATypeFromAnotherFile returned.");
     delete abcParam.z;
     abcParam.z = NULL;
+}
 
+TEST_F(HidlTest, FooHaveSomeStringsTest) {
     ALOGI("CLIENT call haveSomeStrings.");
     hidl_string stringArrayParam[3];
     stringArrayParam[0] = "What";
     stringArrayParam[1] = "a";
     stringArrayParam[2] = "disaster";
-    foo->haveSomeStrings(stringArrayParam);
+    EXPECT_OK(foo->haveSomeStrings(stringArrayParam));
     ALOGI("CLIENT haveSomeStrings returned.");
+}
 
+TEST_F(HidlTest, FooHaveAStringVecTest) {
     ALOGI("CLIENT call haveAStringVec.");
     hidl_vec<hidl_string> stringVecParam;
     stringVecParam.resize(3);
     stringVecParam[0] = "What";
     stringVecParam[1] = "a";
     stringVecParam[2] = "disaster";
-    foo->haveAStringVec(stringVecParam);
+    EXPECT_OK(foo->haveAStringVec(stringVecParam));
     ALOGI("CLIENT haveAStringVec returned.");
+}
 
+TEST_F(HidlTest, BarThisIsNewTest) {
     // Now the tricky part, get access to the derived interface.
-
-    sp<IBar> bar = IBar::asInterface(service);
-    CHECK(bar != NULL);
-
     ALOGI("CLIENT call thisIsNew.");
-    bar->thisIsNew();
+    EXPECT_OK(bar->thisIsNew());
     ALOGI("CLIENT thisIsNew returned.");
 }
 
-int main() {
-    using namespace android::hardware;
-    using android::String16;
+int main(int argc, char **argv) {
 
-    if (fork() == 0) {
-        sleep(1);
+    ::testing::AddGlobalTestEnvironment(new HidlEnvironment);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
 
-        // Fear me, I am child.
-        client();
-
-        return 0;
-    }
-
-    if (fork() == 0) {
-        ALOGI("SERVER(FooCallback) registering");
-        sp<FooCallback> fcb = new FooCallback;
-        const hidl_version kVersion = make_hidl_version(1, 0);
-        defaultServiceManager()->addService(String16("foo callback"), fcb, kVersion);
-        ALOGI("SERVER(FooCallback) starting");
-        ProcessState::self()->setThreadPoolMaxThreadCount(0);
-        ProcessState::self()->startThreadPool();
-        IPCThreadState::self()->joinThreadPool();
-
-        return 0;
-    }
-
-    ALOGI("SERVER(Bar) registering");
-    sp<Bar> bar = new Bar;
-    const hidl_version kVersion = make_hidl_version(1, 0);
-    defaultServiceManager()->addService(String16("foo"), bar, kVersion);
-    ALOGI("SERVER(Bar) starting");
-    ProcessState::self()->setThreadPoolMaxThreadCount(0);
-    ProcessState::self()->startThreadPool();
-    IPCThreadState::self()->joinThreadPool();
-
-    return 0;
+    ALOGI("Test result = %d", status);
+    return status;
 }