Merge "Change sytle of radio and sap tests to clang google" into oc-dev
diff --git a/automotive/Android.bp b/automotive/Android.bp
index 9b24ded..aec8865 100644
--- a/automotive/Android.bp
+++ b/automotive/Android.bp
@@ -2,6 +2,7 @@
 subdirs = [
     "evs/1.0",
     "evs/1.0/default",
+    "evs/1.0/vts/functional",
     "vehicle/2.0",
     "vehicle/2.1",
 ]
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..22ceff3
--- /dev/null
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsEvsV1_0Target",
+
+    srcs: [
+        "VtsEvsV1_0TargetTest.cpp",
+        "FrameHandler.cpp"
+    ],
+
+    defaults: [
+        "hidl_defaults",
+    ],
+
+    shared_libs: [
+        "android.hardware.automotive.evs@1.0",
+        "liblog",
+        "libutils",
+        "libui",
+        "libhidlbase",
+        "libhidltransport",
+    ],
+
+    static_libs: ["VtsHalHidlTargetTestBase"],
+
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
+
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
new file mode 100644
index 0000000..01d9a0e
--- /dev/null
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalEvsTest"
+
+#include "FrameHandler.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <android/log.h>
+#include <cutils/native_handle.h>
+#include <ui/GraphicBufferMapper.h>
+#include <ui/GraphicBuffer.h>
+
+#include <algorithm>    // std::min
+
+
+// For the moment, we're assuming that the underlying EVS driver we're working with
+// is providing 4 byte RGBx data.  This is fine for loopback testing, although
+// real hardware is expected to provide YUV data -- most likly formatted as YV12
+static const unsigned kBytesPerPixel = 4;   // assuming 4 byte RGBx pixels
+
+
+FrameHandler::FrameHandler(android::sp <IEvsCamera> pCamera, CameraDesc cameraInfo,
+                           android::sp <IEvsDisplay> pDisplay,
+                           BufferControlFlag mode) :
+    mCamera(pCamera),
+    mCameraInfo(cameraInfo),
+    mDisplay(pDisplay),
+    mReturnMode(mode) {
+    // Nothing but member initialization here...
+}
+
+
+void FrameHandler::shutdown()
+{
+    // Make sure we're not still streaming
+    blockingStopStream();
+
+    // At this point, the receiver thread is no longer running, so we can safely drop
+    // our remote object references so they can be freed
+    mCamera = nullptr;
+    mDisplay = nullptr;
+}
+
+
+bool FrameHandler::startStream() {
+    // Mark ourselves as running
+    mLock.lock();
+    mRunning = true;
+    mLock.unlock();
+
+    // Tell the camera to start streaming
+    Return<EvsResult> result = mCamera->startVideoStream(this);
+    return (result == EvsResult::OK);
+}
+
+
+void FrameHandler::asyncStopStream() {
+    // Tell the camera to stop streaming.
+    // This will result in a null frame being delivered when the stream actually stops.
+    mCamera->stopVideoStream();
+}
+
+
+void FrameHandler::blockingStopStream() {
+    // Tell the stream to stop
+    asyncStopStream();
+
+    // Wait until the stream has actually stopped
+    std::unique_lock<std::mutex> lock(mLock);
+    mSignal.wait(lock, [this](){ return !mRunning; });
+}
+
+
+bool FrameHandler::returnHeldBuffer() {
+    std::unique_lock<std::mutex> lock(mLock);
+
+    // Return the oldest buffer we're holding
+    if (mHeldBuffers.empty()) {
+        // No buffers are currently held
+        return false;
+    }
+
+    BufferDesc buffer = mHeldBuffers.front();
+    mHeldBuffers.pop();
+    mCamera->doneWithFrame(buffer);
+
+    return true;
+}
+
+
+bool FrameHandler::isRunning() {
+    std::unique_lock<std::mutex> lock(mLock);
+    return mRunning;
+}
+
+
+void FrameHandler::waitForFrameCount(unsigned frameCount) {
+    // Wait until we've seen at least the requested number of frames (could be more)
+    std::unique_lock<std::mutex> lock(mLock);
+    mSignal.wait(lock, [this, frameCount](){ return mFramesReceived >= frameCount; });
+}
+
+
+void FrameHandler::getFramesCounters(unsigned* received, unsigned* displayed) {
+    std::unique_lock<std::mutex> lock(mLock);
+
+    if (received) {
+        *received = mFramesReceived;
+    }
+    if (displayed) {
+        *displayed = mFramesDisplayed;
+    }
+}
+
+
+Return<void> FrameHandler::deliverFrame(const BufferDesc& bufferArg) {
+    ALOGD("Received a frame from the camera (%p)", bufferArg.memHandle.getNativeHandle());
+
+    // Local flag we use to keep track of when the stream is stopping
+    bool timeToStop = false;
+
+    // TODO:  Why do we get a gralloc crash if we don't clone the buffer here?
+    BufferDesc buffer(bufferArg);
+    ALOGD("Clone the received frame as %p", buffer.memHandle.getNativeHandle());
+
+    if (buffer.memHandle.getNativeHandle() == nullptr) {
+        // Signal that the last frame has been received and the stream is stopped
+        timeToStop = true;
+    } else {
+        // If we were given an opened display at construction time, then send the received
+        // image back down the camera.
+        if (mDisplay.get()) {
+            // Get the output buffer we'll use to display the imagery
+            BufferDesc tgtBuffer = {};
+            mDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc& buff) {
+                                          tgtBuffer = buff;
+                                      }
+            );
+
+            if (tgtBuffer.memHandle == nullptr) {
+                printf("Didn't get target buffer - frame lost\n");
+                ALOGE("Didn't get requested output buffer -- skipping this frame.");
+            } else {
+                // In order for the handles passed through HIDL and stored in the BufferDesc to
+                // be lockable, we must register them with GraphicBufferMapper
+                registerBufferHelper(tgtBuffer);
+                registerBufferHelper(buffer);
+
+                // Copy the contents of the of buffer.memHandle into tgtBuffer
+                copyBufferContents(tgtBuffer, buffer);
+
+                // Send the target buffer back for display
+                Return <EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
+                if (!result.isOk()) {
+                    printf("HIDL error on display buffer (%s)- frame lost\n",
+                           result.description().c_str());
+                    ALOGE("Error making the remote function call.  HIDL said %s",
+                          result.description().c_str());
+                } else if (result != EvsResult::OK) {
+                    printf("Display reported error - frame lost\n");
+                    ALOGE("We encountered error %d when returning a buffer to the display!",
+                          (EvsResult) result);
+                } else {
+                    // Everything looks good!
+                    // Keep track so tests or watch dogs can monitor progress
+                    mLock.lock();
+                    mFramesDisplayed++;
+                    mLock.unlock();
+                }
+
+                // Now tell GraphicBufferMapper we won't be using these handles anymore
+                unregisterBufferHelper(tgtBuffer);
+                unregisterBufferHelper(buffer);
+            }
+        }
+
+
+        switch (mReturnMode) {
+        case eAutoReturn:
+            // Send the camera buffer back now that we're done with it
+            ALOGD("Calling doneWithFrame");
+            // TODO:  Why is it that we get a HIDL crash if we pass back the cloned buffer?
+            mCamera->doneWithFrame(bufferArg);
+            break;
+        case eNoAutoReturn:
+            // Hang onto the buffer handle for now -- we'll return it explicitly later
+            mHeldBuffers.push(bufferArg);
+        }
+
+
+        ALOGD("Frame handling complete");
+    }
+
+
+    // Update our received frame count and notify anybody who cares that things have changed
+    mLock.lock();
+    if (timeToStop) {
+        mRunning = false;
+    } else {
+        mFramesReceived++;
+    }
+    mLock.unlock();
+    mSignal.notify_all();
+
+
+    return Void();
+}
+
+
+bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer,
+                                      const BufferDesc& srcBuffer) {
+    bool success = true;
+
+    // Make sure we don't run off the end of either buffer
+    const unsigned width     = std::min(tgtBuffer.width,
+                                        srcBuffer.width);
+    const unsigned height    = std::min(tgtBuffer.height,
+                                        srcBuffer.height);
+
+    android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+
+
+    // Lock our source buffer for reading
+    unsigned char* srcPixels = nullptr;
+    mapper.registerBuffer(srcBuffer.memHandle);
+    mapper.lock(srcBuffer.memHandle,
+                GRALLOC_USAGE_SW_READ_OFTEN,
+                android::Rect(width, height),
+                (void **) &srcPixels);
+
+    // Lock our target buffer for writing
+    unsigned char* tgtPixels = nullptr;
+    mapper.registerBuffer(tgtBuffer.memHandle);
+    mapper.lock(tgtBuffer.memHandle,
+                GRALLOC_USAGE_SW_WRITE_OFTEN,
+                android::Rect(width, height),
+                (void **) &tgtPixels);
+
+    if (srcPixels && tgtPixels) {
+        for (unsigned row = 0; row < height; row++) {
+            // Copy the entire row of pixel data
+            memcpy(tgtPixels, srcPixels, width * kBytesPerPixel);
+
+            // Advance to the next row (keeping in mind that stride here is in units of pixels)
+            tgtPixels += tgtBuffer.stride * kBytesPerPixel;
+            srcPixels += srcBuffer.stride * kBytesPerPixel;
+        }
+    } else {
+        ALOGE("Failed to copy buffer contents");
+        success = false;
+    }
+
+    if (srcPixels) {
+        mapper.unlock(srcBuffer.memHandle);
+    }
+    if (tgtPixels) {
+        mapper.unlock(tgtBuffer.memHandle);
+    }
+    mapper.unregisterBuffer(srcBuffer.memHandle);
+    mapper.unregisterBuffer(tgtBuffer.memHandle);
+
+    return success;
+}
+
+
+void FrameHandler::registerBufferHelper(const BufferDesc& buffer)
+{
+    // In order for the handles passed through HIDL and stored in the BufferDesc to
+    // be lockable, we must register them with GraphicBufferMapper.
+    // If the device upon which we're running supports gralloc1, we could just call
+    // registerBuffer directly with the handle.  But that call  is broken for gralloc0 devices
+    // (which we care about, at least for now).  As a result, we have to synthesize a GraphicBuffer
+    // object around the buffer handle in order to make a call to the overloaded alternate
+    // version of the registerBuffer call that does happen to work on gralloc0 devices.
+#if REGISTER_BUFFER_ALWAYS_WORKS
+    android::GraphicBufferMapper::get().registerBuffer(buffer.memHandle);
+#else
+    android::sp<android::GraphicBuffer> pGfxBuff = new android::GraphicBuffer(
+            buffer.width, buffer.height, buffer.format,
+            1, /* we always use exactly one layer */
+            buffer.usage, buffer.stride,
+            const_cast<native_handle_t*>(buffer.memHandle.getNativeHandle()),
+            false /* GraphicBuffer should not try to free the handle */
+    );
+
+    android::GraphicBufferMapper::get().registerBuffer(pGfxBuff.get());
+#endif
+}
+
+
+void FrameHandler::unregisterBufferHelper(const BufferDesc& buffer)
+{
+    // Now tell GraphicBufferMapper we won't be using these handles anymore
+    android::GraphicBufferMapper::get().unregisterBuffer(buffer.memHandle);
+}
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.h b/automotive/evs/1.0/vts/functional/FrameHandler.h
new file mode 100644
index 0000000..d5c3f6b
--- /dev/null
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EVS_VTS_FRAMEHANDLER_H
+#define EVS_VTS_FRAMEHANDLER_H
+
+#include <queue>
+
+#include <android/hardware/automotive/evs/1.0/IEvsCameraStream.h>
+#include <android/hardware/automotive/evs/1.0/IEvsCamera.h>
+#include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
+
+using namespace ::android::hardware::automotive::evs::V1_0;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_handle;
+using ::android::sp;
+
+
+/*
+ * FrameHandler:
+ * This class can be used to receive camera imagery from an IEvsCamera implementation.  Given an
+ * IEvsDisplay instance at startup, it will forward the received imagery to the display,
+ * providing a trivial implementation of a rear vew camera type application.
+ * Note that the video frames are delivered on a background thread, while the control interface
+ * is actuated from the applications foreground thread.
+ */
+class FrameHandler : public IEvsCameraStream {
+public:
+    enum BufferControlFlag {
+        eAutoReturn,
+        eNoAutoReturn,
+    };
+
+    FrameHandler(android::sp <IEvsCamera> pCamera, CameraDesc cameraInfo,
+                 android::sp <IEvsDisplay> pDisplay = nullptr,
+                 BufferControlFlag mode = eAutoReturn);
+    void shutdown();
+
+    bool startStream();
+    void asyncStopStream();
+    void blockingStopStream();
+
+    bool returnHeldBuffer();
+
+    bool isRunning();
+
+    void waitForFrameCount(unsigned frameCount);
+    void getFramesCounters(unsigned* received, unsigned* displayed);
+
+private:
+    // Implementation for ::android::hardware::automotive::evs::V1_0::ICarCameraStream
+    Return<void> deliverFrame(const BufferDesc& buffer)  override;
+
+    // Local implementation details
+    bool copyBufferContents(const BufferDesc& tgtBuffer, const BufferDesc& srcBuffer);
+    void registerBufferHelper(const BufferDesc& buffer);
+    void unregisterBufferHelper(const BufferDesc& buffer);
+
+    // Values initialized as startup
+    android::sp <IEvsCamera>    mCamera;
+    CameraDesc                  mCameraInfo;
+    android::sp <IEvsDisplay>   mDisplay;
+    BufferControlFlag           mReturnMode;
+
+    // Since we get frames delivered to us asnchronously via the ICarCameraStream interface,
+    // we need to protect all member variables that may be modified while we're streaming
+    // (ie: those below)
+    std::mutex                  mLock;
+    std::condition_variable     mSignal;
+
+    std::queue<BufferDesc>      mHeldBuffers;
+    bool                        mRunning = false;
+    unsigned                    mFramesReceived = 0;    // Simple counter -- rolls over eventually!
+    unsigned                    mFramesDisplayed = 0;   // Simple counter -- rolls over eventually!
+};
+
+
+#endif //EVS_VTS_FRAMEHANDLER_H
diff --git a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
new file mode 100644
index 0000000..6a0ae48
--- /dev/null
+++ b/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalEvsTest"
+
+
+// TODO:  How should we configure these values to target appropriate hardware?
+const static char kEnumeratorName[]  = "EvsEnumeratorHw-Mock";
+
+
+// These values are called out in the EVS design doc (as of Mar 8, 2017)
+static const int kMaxStreamStartMilliseconds = 500;
+static const int kMinimumFramesPerSecond = 10;
+
+static const int kSecondsToMilliseconds = 1000;
+static const int kMillisecondsToMicroseconds = 1000;
+static const float kNanoToMilliseconds = 0.000001f;
+static const float kNanoToSeconds = 0.000000001f;
+
+
+#include "FrameHandler.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/Log.h>
+#include <hwbinder/ProcessState.h>
+
+#include <android/log.h>
+#include <android/hardware/automotive/evs/1.0/IEvsCamera.h>
+#include <android/hardware/automotive/evs/1.0/IEvsEnumerator.h>
+#include <android/hardware/automotive/evs/1.0/IEvsCameraStream.h>
+#include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+
+using namespace ::android::hardware::automotive::evs::V1_0;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+
+// The main test class for EVS
+class EvsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+public:
+    virtual void SetUp() override {
+        // Make sure we can connect to the enumerator
+        pEnumerator = IEvsEnumerator::getService(kEnumeratorName);
+        ASSERT_NE(pEnumerator.get(), nullptr);
+    }
+
+    virtual void TearDown() override {}
+
+protected:
+    void loadCameraList() {
+        // SetUp() must run first!
+        assert(pEnumerator != nullptr);
+
+        // Get the camera list
+        pEnumerator->getCameraList([this](hidl_vec <CameraDesc> cameraList) {
+                                       ALOGI("Camera list callback received %zu cameras",
+                                             cameraList.size());
+                                       cameraInfo.reserve(cameraList.size());
+                                       for (auto&& cam: cameraList) {
+                                           ALOGI("Found camera %s", cam.cameraId.c_str());
+                                           cameraInfo.push_back(cam);
+                                       }
+                                   }
+        );
+
+        // We insist on at least one camera for EVS to pass any camera tests
+        ASSERT_GE(cameraInfo.size(), 1u);
+    }
+
+    sp<IEvsEnumerator>          pEnumerator;    // Every test needs access to the service
+    std::vector <CameraDesc>    cameraInfo;     // Empty unless/until loadCameraList() is called
+};
+
+
+//
+// Tests start here...
+//
+
+/*
+ * CameraOpenClean:
+ * Opens each camera reported by the enumerator and then explicitly closes it via a
+ * call to closeCamera.  Then repeats the test to ensure all cameras can be reopened.
+ */
+TEST_F(EvsHidlTest, CameraOpenClean) {
+    // Get the camera list
+    loadCameraList();
+
+    // Open and close each camera twice
+    for (auto&& cam: cameraInfo) {
+        for (int pass = 0; pass < 2; pass++) {
+            sp<IEvsCamera> pCam = pEnumerator->openCamera(cam.cameraId);
+            ASSERT_NE(pCam, nullptr);
+
+            // Verify that this camera self-identifies correctly
+            pCam->getCameraInfo([&cam](CameraDesc desc) {
+                                    ALOGD("Found camera %s", desc.cameraId.c_str());
+                                    EXPECT_EQ(cam.cameraId, desc.cameraId);
+                                }
+            );
+
+            // Explicitly close the camera so resources are released right away
+            pEnumerator->closeCamera(pCam);
+        }
+    }
+}
+
+
+/*
+ * CameraOpenAggressive:
+ * Opens each camera reported by the enumerator twice in a row without an intervening closeCamera
+ * call.  This ensures that the intended "aggressive open" behavior works.  This is necessary for
+ * the system to be tolerant of shutdown/restart race conditions.
+ */
+TEST_F(EvsHidlTest, CameraOpenAggressive) {
+    // Get the camera list
+    loadCameraList();
+
+    // Open and close each camera twice
+    for (auto&& cam: cameraInfo) {
+        sp<IEvsCamera> pCam = pEnumerator->openCamera(cam.cameraId);
+        ASSERT_NE(pCam, nullptr);
+
+        // Verify that this camera self-identifies correctly
+        pCam->getCameraInfo([&cam](CameraDesc desc) {
+                                ALOGD("Found camera %s", desc.cameraId.c_str());
+                                EXPECT_EQ(cam.cameraId, desc.cameraId);
+                            }
+        );
+
+        sp<IEvsCamera> pCam2 = pEnumerator->openCamera(cam.cameraId);
+        ASSERT_NE(pCam, pCam2);
+        ASSERT_NE(pCam2, nullptr);
+
+        // Verify that the old camera rejects calls
+        Return<EvsResult> badResult = pCam->setMaxFramesInFlight(2);
+        EXPECT_EQ(EvsResult::OWNERSHIP_LOST, EvsResult(badResult));
+
+        // Close the superceded camera
+        pEnumerator->closeCamera(pCam);
+
+        // Verify that the second camera instance self-identifies correctly
+        pCam2->getCameraInfo([&cam](CameraDesc desc) {
+                                 ALOGD("Found camera %s", desc.cameraId.c_str());
+                                 EXPECT_EQ(cam.cameraId, desc.cameraId);
+                             }
+        );
+
+        // Leave the second camera dangling so it gets cleaned up by the destructor path
+    }
+
+    // Sleep here to ensure the destructor cleanup has time to run so we don't break follow on tests
+    sleep(1);   // I hate that this is an arbitrary time to wait.  :(  b/36122635
+}
+
+
+/*
+ * DisplayOpen:
+ * Test both clean shut down and "aggressive open" device stealing behavior.
+ */
+TEST_F(EvsHidlTest, DisplayOpen) {
+    // Request exclusive access to the EVS display, then let it go
+    {
+        sp<IEvsDisplay> pDisplay = pEnumerator->openDisplay();
+        ASSERT_NE(pDisplay, nullptr);
+
+        // Ask the display what it's name is
+        pDisplay->getDisplayInfo([](DisplayDesc desc) {
+                                     ALOGD("Found display %s", desc.displayId.c_str());
+                                 }
+        );
+
+        pEnumerator->closeDisplay(pDisplay);
+    }
+
+    // Ensure we can reopen the display after it has been closed
+    {
+        // Reopen the display
+        sp<IEvsDisplay> pDisplay = pEnumerator->openDisplay();
+        ASSERT_NE(pDisplay, nullptr);
+
+        // Open the display while its already open -- ownership should be transferred
+        sp<IEvsDisplay> pDisplay2 = pEnumerator->openDisplay();
+        ASSERT_NE(pDisplay2, nullptr);
+
+        // Ensure the old display properly reports its assassination
+        Return<DisplayState> badResult = pDisplay->getDisplayState();
+        EXPECT_EQ(badResult, DisplayState::DEAD);
+
+        // Close only the newest display instance -- the other should already be a zombie
+        pEnumerator->closeDisplay(pDisplay2);
+    }
+
+    // Finally, validate that we can open the display after the provoked failure above
+    sp<IEvsDisplay> pDisplay = pEnumerator->openDisplay();
+    ASSERT_NE(pDisplay, nullptr);
+
+    pEnumerator->closeDisplay(pDisplay);
+}
+
+
+/*
+ * DisplayStates:
+ * Validate that display states transition as expected and can be queried from either the display
+ * object itself or the owning enumerator.
+ */
+TEST_F(EvsHidlTest, DisplayStates) {
+    // Ensure the display starts in the expected state
+    EXPECT_EQ((DisplayState)pEnumerator->getDisplayState(), DisplayState::NOT_OPEN);
+
+    // Scope to limit the lifetime of the pDisplay pointer, and thus the IEvsDisplay object
+    {
+        // Request exclusive access to the EVS display
+        sp<IEvsDisplay> pDisplay = pEnumerator->openDisplay();
+        ASSERT_NE(pDisplay, nullptr);
+        EXPECT_EQ((DisplayState)pEnumerator->getDisplayState(), DisplayState::NOT_VISIBLE);
+
+        // Activate the display
+        pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME);
+        EXPECT_EQ((DisplayState)pEnumerator->getDisplayState(), DisplayState::VISIBLE_ON_NEXT_FRAME);
+        EXPECT_EQ((DisplayState)pDisplay->getDisplayState(), DisplayState::VISIBLE_ON_NEXT_FRAME);
+
+        // Get the output buffer we'd use to display the imagery
+        BufferDesc tgtBuffer = {};
+        pDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc& buff) {
+                                      tgtBuffer = buff;
+                                  }
+        );
+        EXPECT_NE(tgtBuffer.memHandle, nullptr);
+
+        // Send the target buffer back for display (we didn't actually fill anything)
+        pDisplay->returnTargetBufferForDisplay(tgtBuffer);
+
+        // Sleep for a tenth of a second to ensure the driver has time to get the image displayed
+        usleep(100 * kMillisecondsToMicroseconds);
+        EXPECT_EQ((DisplayState)pEnumerator->getDisplayState(), DisplayState::VISIBLE);
+        EXPECT_EQ((DisplayState)pDisplay->getDisplayState(), DisplayState::VISIBLE);
+
+        // Turn off the display
+        pDisplay->setDisplayState(DisplayState::NOT_VISIBLE);
+        usleep(100 * kMillisecondsToMicroseconds);
+        EXPECT_EQ((DisplayState)pEnumerator->getDisplayState(), DisplayState::NOT_VISIBLE);
+
+        // Close the display
+        pEnumerator->closeDisplay(pDisplay);
+    }
+
+    // TODO:  This hack shouldn't be necessary.  b/36122635
+// NOTE:  Calling flushCommand here did not avoid the race.  Going back to sleep...  :(
+//    android::hardware::IPCThreadState::self()->flushCommands();
+    sleep(1);
+
+    // Now that the display pointer has gone out of scope, causing the IEvsDisplay interface
+    // object to be destroyed, we should be back to the "not open" state.
+    // NOTE:  If we want this to pass without the sleep above, we'd have to add the
+    //        (now recommended) closeDisplay() call instead of relying on the smarter pointer
+    //        going out of scope.
+    EXPECT_EQ((DisplayState)pEnumerator->getDisplayState(), DisplayState::NOT_OPEN);
+}
+
+
+/*
+ * CameraStreamPerformance:
+ * Measure and qualify the stream start up time and streaming frame rate of each reported camera
+ */
+TEST_F(EvsHidlTest, CameraStreamPerformance) {
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam: cameraInfo) {
+        sp <IEvsCamera> pCam = pEnumerator->openCamera(cam.cameraId);
+        ASSERT_NE(pCam, nullptr);
+
+        // Set up a frame receiver object which will fire up its own thread
+        sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
+                                                         nullptr,
+                                                         FrameHandler::eAutoReturn);
+
+        // Start the camera's video stream
+        nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
+        bool startResult = frameHandler->startStream();
+        EXPECT_EQ(startResult, true);
+
+        // Ensure the first frame arrived within the expected time
+        frameHandler->waitForFrameCount(1);
+        nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
+        nsecs_t timeToFirstFrame = systemTime(SYSTEM_TIME_MONOTONIC) - start;
+        EXPECT_LE(nanoseconds_to_milliseconds(timeToFirstFrame), kMaxStreamStartMilliseconds);
+        printf("Measured time to first frame %0.2f ms\n", timeToFirstFrame * kNanoToMilliseconds);
+        ALOGI("Measured time to first frame %0.2f ms", timeToFirstFrame * kNanoToMilliseconds);
+
+        // Wait a bit, then ensure we get at least the required minimum number of frames
+        sleep(5);
+        nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
+        unsigned framesReceived = 0;
+        frameHandler->getFramesCounters(&framesReceived, nullptr);
+        framesReceived = framesReceived - 1;    // Back out the first frame we already waited for
+        nsecs_t runTime = end - firstFrame;
+        float framesPerSecond = framesReceived / (runTime * kNanoToSeconds);
+        printf("Measured camera rate %3.2f fps\n", framesPerSecond);
+        ALOGI("Measured camera rate %3.2f fps", framesPerSecond);
+        EXPECT_GE(framesPerSecond, kMinimumFramesPerSecond);
+
+        // Even when the camera pointer goes out of scope, the FrameHandler object will
+        // keep the stream alive unless we tell it to shutdown.
+        // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+        // we have to break that cycle in order for either of them to get cleaned up.
+        frameHandler->shutdown();
+
+        // Explicitly release the camera
+        pEnumerator->closeCamera(pCam);
+    }
+}
+
+
+/*
+ * CameraStreamBuffering:
+ * Ensure the camera implementation behaves properly when the client holds onto buffers for more
+ * than one frame time.  The camera must cleanly skip frames until the client is ready again.
+ */
+TEST_F(EvsHidlTest, CameraStreamBuffering) {
+    // Arbitrary constant (should be > 1 and less than crazy)
+    static const unsigned int kBuffersToHold = 6;
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam: cameraInfo) {
+
+        sp<IEvsCamera> pCam = pEnumerator->openCamera(cam.cameraId);
+        ASSERT_NE(pCam, nullptr);
+
+        // Ask for a crazy number of buffers in flight to ensure it errors correctly
+        Return<EvsResult> badResult = pCam->setMaxFramesInFlight(0xFFFFFFFF);
+        EXPECT_EQ(EvsResult::BUFFER_NOT_AVAILABLE, badResult);
+
+        // Now ask for exactly two buffers in flight as we'll test behavior in that case
+        Return<EvsResult> goodResult = pCam->setMaxFramesInFlight(kBuffersToHold);
+        EXPECT_EQ(EvsResult::OK, goodResult);
+
+
+        // Set up a frame receiver object which will fire up its own thread.
+        sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
+                                                         nullptr,
+                                                         FrameHandler::eNoAutoReturn);
+
+        // Start the camera's video stream
+        bool startResult = frameHandler->startStream();
+        EXPECT_TRUE(startResult);
+
+        // Check that the video stream stalls once we've gotten exactly the number of buffers
+        // we requested since we told the frameHandler not to return them.
+        sleep(1);   // 1 second would be enough for at least 5 frames to be delivered worst case
+        unsigned framesReceived = 0;
+        frameHandler->getFramesCounters(&framesReceived, nullptr);
+        EXPECT_EQ(kBuffersToHold, framesReceived);
+
+
+        // Give back one buffer
+        bool didReturnBuffer = frameHandler->returnHeldBuffer();
+        EXPECT_TRUE(didReturnBuffer);
+
+        // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
+        // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+        usleep(110 * kMillisecondsToMicroseconds);
+        frameHandler->getFramesCounters(&framesReceived, nullptr);
+        EXPECT_EQ(kBuffersToHold+1, framesReceived);
+
+        // Even when the camera pointer goes out of scope, the FrameHandler object will
+        // keep the stream alive unless we tell it to shutdown.
+        // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+        // we have to break that cycle in order for either of them to get cleaned up.
+        frameHandler->shutdown();
+
+        // Explicitly release the camera
+        pEnumerator->closeCamera(pCam);
+    }
+}
+
+
+/*
+ * CameraToDisplayRoundTrip:
+ * End to end test of data flowing from the camera to the display.  Each delivered frame of camera
+ * imagery is simply copied to the display buffer and presented on screen.  This is the one test
+ * which a human could observe to see the operation of the system on the physical display.
+ */
+TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) {
+    // Get the camera list
+    loadCameraList();
+
+    // Request exclusive access to the EVS display
+    sp<IEvsDisplay> pDisplay = pEnumerator->openDisplay();
+    ASSERT_NE(pDisplay, nullptr);
+
+    // Test each reported camera
+    for (auto&& cam: cameraInfo) {
+        sp <IEvsCamera> pCam = pEnumerator->openCamera(cam.cameraId);
+        ASSERT_NE(pCam, nullptr);
+
+        // Set up a frame receiver object which will fire up its own thread.
+        sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
+                                                         pDisplay,
+                                                         FrameHandler::eAutoReturn);
+
+
+        // Activate the display
+        pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME);
+
+        // Start the camera's video stream
+        bool startResult = frameHandler->startStream();
+        EXPECT_EQ(startResult, true);
+
+        // Wait a while to let the data flow
+        static const int kSecondsToWait = 5;
+        const int streamTimeMs = kSecondsToWait * kSecondsToMilliseconds -
+                                 kMaxStreamStartMilliseconds;
+        const unsigned minimumFramesExpected = streamTimeMs * kMinimumFramesPerSecond /
+                                               kSecondsToMilliseconds;
+        sleep(kSecondsToWait);
+        unsigned framesReceived = 0;
+        unsigned framesDisplayed = 0;
+        frameHandler->getFramesCounters(&framesReceived, &framesDisplayed);
+        EXPECT_EQ(framesReceived, framesDisplayed);
+        EXPECT_GE(framesDisplayed, minimumFramesExpected);
+
+        // Turn off the display (yes, before the stream stops -- it should be handled)
+        pDisplay->setDisplayState(DisplayState::NOT_VISIBLE);
+
+        // Shut down the streamer
+        frameHandler->shutdown();
+
+        // Explicitly release the camera
+        pEnumerator->closeCamera(pCam);
+    }
+
+    // Explicitly release the display
+    pEnumerator->closeDisplay(pDisplay);
+}
\ No newline at end of file
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 546aa12..36d7d1c 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -15,7 +15,7 @@
 //
 
 cc_test {
-    name: "drm_hidl_test",
+    name: "VtsHalDrmV1_0TargetTest",
     srcs: [
         "drm_hal_clearkey_test.cpp",
         "drm_hal_vendor_test.cpp",