Initial Android Auto External View Systems drivers

Add support for EVS system camera and display drivers.
These build and run but still contain significant placeholder code and
TODO items.

Bug: 32095143
Test:  run against evs_test (submitted in future change set)
Change-Id: I9187e888f03248e5cd43293253dc76a71184c02d
diff --git a/evs/1.0/default/Android.bp b/evs/1.0/default/Android.bp
new file mode 100644
index 0000000..3bda250
--- /dev/null
+++ b/evs/1.0/default/Android.bp
@@ -0,0 +1,26 @@
+cc_binary {
+    name: "android.hardware.evs@1.0-service",
+    relative_install_path: "hw",
+    srcs: [
+        "service.cpp",
+        "EvsCamera.cpp",
+        "EvsEnumerator.cpp",
+        "EvsDisplay.cpp"
+    ],
+    init_rc: ["android.hardware.evs@1.0-service.rc"],
+
+    shared_libs: [
+        "android.hardware.evs@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "libui",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/evs/1.0/default/EvsCamera.cpp b/evs/1.0/default/EvsCamera.cpp
new file mode 100644
index 0000000..32d4ed7
--- /dev/null
+++ b/evs/1.0/default/EvsCamera.cpp
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.evs@1.0-service"
+
+#include "EvsCamera.h"
+
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
+
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+
+// These are the special camera names for which we'll initialize custom test data
+const char EvsCamera::kCameraName_Backup[]    = "backup";
+const char EvsCamera::kCameraName_RightTurn[] = "Right Turn";
+
+
+// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
+// As it stands, if the client dies suddently, the buffer may be stranded.
+// As possible work around would be to give the client a HIDL object to exclusively hold
+// and use it's destructor to perform some work in the server side.
+
+EvsCamera::EvsCamera(const char *id) {
+    ALOGD("EvsCamera instantiated");
+
+    mDescription.cameraId = id;
+    mFrameBusy = false;
+    mStreamState = STOPPED;
+
+    // Set up dummy data for testing
+    if (mDescription.cameraId == kCameraName_Backup) {
+        mDescription.hints                  = UsageHint::USAGE_HINT_REVERSE;
+        mDescription.vendorFlags            = 0xFFFFFFFF;   // Arbitrary value
+        mDescription.defaultHorResolution   = 320;          // 1/2 NTSC/VGA
+        mDescription.defaultVerResolution   = 240;          // 1/2 NTSC/VGA
+    }
+    else if (mDescription.cameraId == kCameraName_RightTurn) {
+        // Nothing but the name and the usage hint
+        mDescription.hints                  = UsageHint::USAGE_HINT_RIGHT_TURN;
+    }
+    else {
+        // Leave empty for a minimalist camera description without even a hint
+    }
+}
+
+EvsCamera::~EvsCamera() {
+    ALOGD("EvsCamera being destroyed");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // Make sure our output stream is cleaned up
+    // (It really should be already)
+    stopVideoStream();
+
+    // Drop the graphics buffer we've been using
+    if (mBuffer) {
+        // Drop the graphics buffer we've been using
+        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+        alloc.free(mBuffer);
+    }
+
+    ALOGD("EvsCamera destroyed");
+}
+
+
+// Methods from ::android::hardware::evs::V1_0::IEvsCamera follow.
+Return<void> EvsCamera::getId(getId_cb id_cb) {
+    ALOGD("getId");
+
+    id_cb(mDescription.cameraId);
+
+    return Void();
+}
+
+
+Return<EvsResult> EvsCamera::setMaxFramesInFlight(uint32_t bufferCount) {
+    ALOGD("setMaxFramesInFlight");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // TODO:  Update our stored value
+
+    // TODO:  Adjust our buffer count right now if we can.  Otherwise, it'll adjust in doneWithFrame
+
+    // For now we support only one!
+    if (bufferCount != 1) {
+        return EvsResult::BUFFER_NOT_AVAILABLE;
+    }
+
+    return EvsResult::OK;
+}
+
+Return<EvsResult> EvsCamera::startVideoStream(const ::android::sp<IEvsCameraStream>& stream)  {
+    ALOGD("startVideoStream");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // We only support a single stream at a time
+    if (mStreamState != STOPPED) {
+        ALOGE("ignoring startVideoStream call when a stream is already running.");
+        return EvsResult::STREAM_ALREADY_RUNNING;
+    }
+
+    // Record the user's callback for use when we have a frame ready
+    mStream = stream;
+
+    // Allocate a graphics buffer into which we'll put our test images
+    if (!mBuffer) {
+        mWidth  = (mDescription.defaultHorResolution) ? mDescription.defaultHorResolution : 640;
+        mHeight = (mDescription.defaultVerResolution) ? mDescription.defaultVerResolution : 480;
+        // TODO:  What about stride?  Assume no padding for now...
+        mStride = 4* mWidth;    // Special cased to assume 4 byte pixels with no padding for now
+
+        ALOGD("Allocating buffer for camera frame");
+        GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
+        status_t result = alloc.allocate(mWidth, mHeight,
+                                         HAL_PIXEL_FORMAT_RGBA_8888, 1, GRALLOC_USAGE_HW_TEXTURE,
+                                         &mBuffer, &mStride, 0, "EvsCamera");
+        if (result != NO_ERROR) {
+            ALOGE("Error %d allocating %d x %d graphics buffer", result, mWidth, mHeight);
+            return EvsResult::BUFFER_NOT_AVAILABLE;
+        }
+        if (!mBuffer) {
+            ALOGE("We didn't get a buffer handle back from the allocator");
+            return EvsResult::BUFFER_NOT_AVAILABLE;
+        }
+    }
+
+    // Start the frame generation thread
+    mStreamState = RUNNING;
+    mCaptureThread = std::thread([this](){GenerateFrames();});
+
+    return EvsResult::OK;
+}
+
+Return<EvsResult> EvsCamera::doneWithFrame(uint32_t frameId, const hidl_handle& bufferHandle)  {
+    ALOGD("doneWithFrame");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    if (!bufferHandle)
+    {
+        ALOGE("ignoring doneWithFrame called with invalid handle");
+        return EvsResult::INVALID_ARG;
+    }
+
+    // TODO:  Track which frames we've delivered and validate this is one of them
+
+    // Mark the frame buffer as available for a new frame
+    mFrameBusy = false;
+
+    // TODO:  If we currently have too many buffers, drop this one
+
+    return EvsResult::OK;
+}
+
+Return<void> EvsCamera::stopVideoStream()  {
+    ALOGD("stopVideoStream");
+
+    bool waitForJoin = false;
+    // Lock scope
+    {
+        std::lock_guard <std::mutex> lock(mAccessLock);
+
+        if (mStreamState == RUNNING) {
+            // Tell the GenerateFrames loop we want it to stop
+            mStreamState = STOPPING;
+
+            // Note that we asked the thread to stop and should wait for it do so
+            waitForJoin = true;
+        }
+    }
+
+    if (waitForJoin) {
+        // Block outside the mutex until the "stop" flag has been acknowledged
+        // NOTE:  We won't send any more frames, but the client might still get one already in flight
+        ALOGD("Waiting for stream thread to end...");
+        mCaptureThread.join();
+
+        // Lock scope
+        {
+            std::lock_guard <std::mutex> lock(mAccessLock);
+            mStreamState = STOPPED;
+        }
+    }
+
+    return Void();
+}
+
+Return<int32_t> EvsCamera::getExtendedInfo(uint32_t opaqueIdentifier)  {
+    ALOGD("getExtendedInfo");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // For any single digit value, return the index itself as a test value
+    if (opaqueIdentifier <= 9) {
+        return opaqueIdentifier;
+    }
+
+    // Return zero by default as required by the spec
+    return 0;
+}
+
+Return<EvsResult> EvsCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, int32_t /*opaqueValue*/)  {
+    ALOGD("setExtendedInfo");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // We don't store any device specific information in this implementation
+    return EvsResult::INVALID_ARG;
+}
+
+
+void EvsCamera::GenerateFrames() {
+    ALOGD("Frame generate loop started");
+
+    uint32_t frameNumber;
+
+    while (true) {
+        bool timeForFrame = false;
+        // Lock scope
+        {
+            std::lock_guard<std::mutex> lock(mAccessLock);
+
+            // Tick the frame counter -- rollover is tolerated
+            frameNumber = mFrameId++;
+
+            if (mStreamState != RUNNING) {
+                // Break out of our main thread loop
+                break;
+            }
+
+            if (mFrameBusy) {
+                // Can't do anything right now -- skip this frame
+                ALOGW("Skipped a frame because client hasn't returned a buffer\n");
+            }
+            else {
+                // We're going to make the frame busy
+                mFrameBusy = true;
+                timeForFrame = true;
+            }
+        }
+
+        if (timeForFrame) {
+            // Lock our output buffer for writing
+            uint32_t *pixels = nullptr;
+            GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+            mapper.lock(mBuffer,
+                        GRALLOC_USAGE_SW_WRITE_OFTEN,
+                        android::Rect(mWidth, mHeight),
+                        (void **) &pixels);
+
+            // If we failed to lock the pixel buffer, we're about to crash, but log it first
+            if (!pixels) {
+                ALOGE("Camera failed to gain access to image buffer for writing");
+            }
+
+            // Fill in the test pixels
+            for (unsigned row = 0; row < mHeight; row++) {
+                for (unsigned col = 0; col < mWidth; col++) {
+                    // Index into the row to set the pixel at this column
+                    // (We're making vertical gradient in the green channel, and
+                    // horitzontal gradient in the blue channel)
+                    pixels[col] = 0xFF0000FF | ((row & 0xFF) << 16) | ((col & 0xFF) << 8);
+                }
+                // Point to the next row
+                pixels = pixels + (mStride / sizeof(*pixels));
+            }
+
+            // Release our output buffer
+            mapper.unlock(mBuffer);
+
+            // Issue the (asynchronous) callback to the client
+            mStream->deliverFrame(frameNumber, mBuffer);
+            ALOGD("Delivered %p as frame %d", mBuffer, frameNumber);
+        }
+
+        // We arbitrarily choose to generate frames at 10 fps (1/10 * uSecPerSec)
+        usleep(100000);
+    }
+
+    // If we've been asked to stop, send one last NULL frame to signal the actual end of stream
+    mStream->deliverFrame(frameNumber, nullptr);
+
+    return;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
diff --git a/evs/1.0/default/EvsCamera.h b/evs/1.0/default/EvsCamera.h
new file mode 100644
index 0000000..5d29125
--- /dev/null
+++ b/evs/1.0/default/EvsCamera.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_EVS_V1_0_EVSCAMERA_H
+#define ANDROID_HARDWARE_EVS_V1_0_EVSCAMERA_H
+
+#include <android/hardware/evs/1.0/types.h>
+#include <android/hardware/evs/1.0/IEvsCamera.h>
+#include <ui/GraphicBuffer.h>
+
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+class EvsCamera : public IEvsCamera {
+public:
+    // Methods from ::android::hardware::evs::V1_0::IEvsCamera follow.
+    Return<void> getId(getId_cb id_cb)  override;
+    Return<EvsResult> setMaxFramesInFlight(uint32_t bufferCount)  override;
+    Return<EvsResult> startVideoStream(const ::android::sp<IEvsCameraStream>& stream) override;
+    Return<EvsResult> doneWithFrame(uint32_t frameId, const hidl_handle& bufferHandle)  override;
+    Return<void> stopVideoStream()  override;
+    Return<int32_t> getExtendedInfo(uint32_t opaqueIdentifier)  override;
+    Return<EvsResult> setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue)  override;
+
+    // Implementation details
+    EvsCamera(const char* id);
+    virtual ~EvsCamera() override;
+
+    const CameraDesc& getDesc() { return mDescription; };
+    void GenerateFrames();
+
+    static const char kCameraName_Backup[];
+    static const char kCameraName_RightTurn[];
+
+private:
+    CameraDesc              mDescription = {};  // The properties of this camera
+
+    buffer_handle_t         mBuffer = nullptr;  // A graphics buffer into which we'll store images
+    uint32_t                mWidth  = 0;        // number of pixels across the buffer
+    uint32_t                mHeight = 0;        // number of pixels vertically in the buffer
+    uint32_t                mStride = 0;        // Bytes per line in the buffer
+
+    sp<IEvsCameraStream>    mStream = nullptr;  // The callback the user expects when a frame is ready
+
+    std::thread             mCaptureThread;     // The thread we'll use to synthesize frames
+
+    uint32_t                mFrameId;           // A frame counter used to identify specific frames
+
+    enum StreamStateValues {
+        STOPPED,
+        RUNNING,
+        STOPPING,
+    };
+    StreamStateValues       mStreamState;
+    bool                    mFrameBusy;         // A flag telling us our one buffer is in use
+
+    std::mutex              mAccessLock;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
+
+#endif  // ANDROID_HARDWARE_EVS_V1_0_EVSCAMERA_H
diff --git a/evs/1.0/default/EvsDisplay.cpp b/evs/1.0/default/EvsDisplay.cpp
new file mode 100644
index 0000000..9dba6fc
--- /dev/null
+++ b/evs/1.0/default/EvsDisplay.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.evs@1.0-service"
+
+#include "EvsDisplay.h"
+
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
+
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+
+// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
+// As it stands, if the client dies suddently, the buffer may be stranded.
+// As possible work around would be to give the client a HIDL object to exclusively hold
+// and use it's destructor to perform some work in the server side.
+
+
+EvsDisplay::EvsDisplay() {
+    ALOGD("EvsDisplay instantiated");
+
+    // Set up our self description
+    mInfo.displayId             = "Mock Display";
+    mInfo.vendorFlags           = 3870;
+    mInfo.defaultHorResolution  = 320;
+    mInfo.defaultVerResolution  = 240;
+}
+
+
+EvsDisplay::~EvsDisplay() {
+    ALOGD("EvsDisplay being destroyed");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // Report if we're going away while a buffer is outstanding.  This could be bad.
+    if (mFrameBusy) {
+        ALOGE("EvsDisplay going down while client is holding a buffer\n");
+    }
+
+    // Make sure we release our frame buffer
+    if (mBuffer) {
+        // Drop the graphics buffer we've been using
+        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+        alloc.free(mBuffer);
+    }
+    ALOGD("EvsDisplay destroyed");
+}
+
+
+/**
+ * Returns basic information about the EVS display provided by the system.
+ * See the description of the DisplayDesc structure below for details.
+ */
+Return<void> EvsDisplay::getDisplayInfo(getDisplayInfo_cb _hidl_cb)  {
+    ALOGD("getDisplayInfo");
+
+    // Send back our self description
+    _hidl_cb(mInfo);
+    return Void();
+}
+
+
+/**
+ * Clients may set the display state to express their desired state.
+ * The HAL implementation must gracefully accept a request for any state
+ * while in any other state, although the response may be to ignore the request.
+ * The display is defined to start in the NOT_VISIBLE state upon initialization.
+ * The client is then expected to request the VISIBLE_ON_NEXT_FRAME state, and
+ * then begin providing video.  When the display is no longer required, the client
+ * is expected to request the NOT_VISIBLE state after passing the last video frame.
+ */
+Return<EvsResult> EvsDisplay::setDisplayState(DisplayState state) {
+    ALOGD("setDisplayState");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // Ensure we recognize the requested state so we don't go off the rails
+    if (state < DisplayState::NUM_STATES) {
+        // Record the requested state
+        mRequestedState = state;
+        return EvsResult::OK;
+    }
+    else {
+        // Turn off the display if asked for an unrecognized state
+        mRequestedState = DisplayState::NOT_VISIBLE;
+        return EvsResult::INVALID_ARG;
+    }
+}
+
+
+/**
+ * The HAL implementation should report the actual current state, which might
+ * transiently differ from the most recently requested state.  Note, however, that
+ * the logic responsible for changing display states should generally live above
+ * the device layer, making it undesirable for the HAL implementation to
+ * spontaneously change display states.
+ */
+Return<DisplayState> EvsDisplay::getDisplayState()  {
+    ALOGD("getDisplayState");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // At the moment, we treat the requested state as immediately active
+    DisplayState currentState = mRequestedState;
+
+    return currentState;
+}
+
+
+/**
+ * This call returns a handle to a frame buffer associated with the display.
+ * This buffer may be locked and written to by software and/or GL.  This buffer
+ * must be returned via a call to returnTargetBufferForDisplay() even if the
+ * display is no longer visible.
+ */
+// TODO: We need to know if/when our client dies so we can get the buffer back! (blocked b/31632518)
+Return<void> EvsDisplay::getTargetBuffer(getTargetBuffer_cb _hidl_cb)  {
+    ALOGD("getTargetBuffer");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // If we don't already have a buffer, allocate one now
+    if (!mBuffer) {
+        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+        status_t result = alloc.allocate(mInfo.defaultHorResolution, mInfo.defaultVerResolution,
+                                         HAL_PIXEL_FORMAT_RGBA_8888, 1,
+                                         GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER,
+                                         &mBuffer, &mStride, 0, "EvsDisplay");
+        mFrameBusy = false;
+        ALOGD("Allocated new buffer %p with stride %u", mBuffer, mStride);
+    }
+
+    // Do we have a frame available?
+    if (mFrameBusy) {
+        // This means either we have a 2nd client trying to compete for buffers
+        // (an unsupported mode of operation) or else the client hasn't returned
+        // a previously issues buffer yet (they're behaving badly).
+        // NOTE:  We have to make callback even if we have nothing to provide
+        ALOGE("getTargetBuffer called while no buffers available.");
+        _hidl_cb(nullptr);
+    }
+    else {
+        // Mark our buffer as busy
+        mFrameBusy = true;
+
+        // Send the buffer to the client
+        ALOGD("Providing display buffer %p", mBuffer);
+        _hidl_cb(mBuffer);
+    }
+
+    // All done
+    return Void();
+}
+
+
+/**
+ * This call tells the display that the buffer is ready for display.
+ * The buffer is no longer valid for use by the client after this call.
+ */
+Return<EvsResult> EvsDisplay::returnTargetBufferForDisplay(const hidl_handle& bufferHandle)  {
+    ALOGD("returnTargetBufferForDisplay %p", bufferHandle.getNativeHandle());
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // This shouldn't happen if we haven't issued the buffer!
+    if (!bufferHandle) {
+        ALOGE ("returnTargetBufferForDisplay called without a valid buffer handle.\n");
+        return EvsResult::INVALID_ARG;
+    }
+    /* TODO(b/33492405): It would be nice to validate we got back the buffer we expect,
+     * but HIDL doesn't support that (yet?)
+    if (bufferHandle != mBuffer) {
+        ALOGE ("Got an unrecognized frame returned.\n");
+        return EvsResult::INVALID_ARG;
+    }
+    */
+    if (!mFrameBusy) {
+        ALOGE ("A frame was returned with no outstanding frames.\n");
+        return EvsResult::BUFFER_NOT_AVAILABLE;
+    }
+
+    mFrameBusy = false;
+
+    // If we were waiting for a new frame, this is it!
+    if (mRequestedState == DisplayState::VISIBLE_ON_NEXT_FRAME) {
+        mRequestedState = DisplayState::VISIBLE;
+    }
+
+    // Validate we're in an expected state
+    if (mRequestedState != DisplayState::VISIBLE) {
+        // We shouldn't get frames back when we're not visible.
+        ALOGE ("Got an unexpected frame returned while not visible - ignoring.\n");
+    }
+    else {
+        // Make this buffer visible
+        // TODO:  Add code to put this image on the screen (or validate it somehow?)
+    }
+
+    return EvsResult::OK;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
diff --git a/evs/1.0/default/EvsDisplay.h b/evs/1.0/default/EvsDisplay.h
new file mode 100644
index 0000000..a2d5d3e
--- /dev/null
+++ b/evs/1.0/default/EvsDisplay.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_EVS_V1_0_EVSDISPLAY_H
+#define ANDROID_HARDWARE_EVS_V1_0_EVSDISPLAY_H
+
+#include <android/hardware/evs/1.0/IEvsDisplay.h>
+#include <ui/GraphicBuffer.h>
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+class EvsDisplay : public IEvsDisplay {
+public:
+    // Methods from ::android::hardware::evs::V1_0::IEvsDisplay follow.
+    Return<void> getDisplayInfo(getDisplayInfo_cb _hidl_cb)  override;
+    Return<EvsResult> setDisplayState(DisplayState state)  override;
+    Return<DisplayState> getDisplayState()  override;
+    Return<void> getTargetBuffer(getTargetBuffer_cb _hidl_cb)  override;
+    Return<EvsResult> returnTargetBufferForDisplay(const hidl_handle& bufferHandle)  override;
+
+    // Implementation details
+    EvsDisplay();
+    virtual ~EvsDisplay() override;
+
+private:
+    DisplayDesc     mInfo           = {};
+    buffer_handle_t mBuffer         = nullptr;      // A graphics buffer into which we'll store images
+    uint32_t        mStride         = 0;            // Bytes per line in the buffer
+
+    bool            mFrameBusy      = false;        // A flag telling us our buffer is in use
+    DisplayState    mRequestedState = DisplayState::NOT_VISIBLE;
+
+    std::mutex      mAccessLock;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
+
+#endif  // ANDROID_HARDWARE_EVS_V1_0_EVSDISPLAY_H
diff --git a/evs/1.0/default/EvsEnumerator.cpp b/evs/1.0/default/EvsEnumerator.cpp
new file mode 100644
index 0000000..9f38041
--- /dev/null
+++ b/evs/1.0/default/EvsEnumerator.cpp
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.evs@1.0-service"
+
+#include "EvsEnumerator.h"
+#include "EvsCamera.h"
+#include "EvsDisplay.h"
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+
+EvsEnumerator::EvsEnumerator() {
+    ALOGD("EvsEnumerator created");
+
+    // Add sample camera data to our list of cameras
+    // NOTE:  The id strings trigger special initialization inside the EvsCamera constructor
+    mCameraList.emplace_back( new EvsCamera(EvsCamera::kCameraName_Backup),    false );
+    mCameraList.emplace_back( new EvsCamera("LaneView"),                       false );
+    mCameraList.emplace_back( new EvsCamera(EvsCamera::kCameraName_RightTurn), false );
+}
+
+// Methods from ::android::hardware::evs::V1_0::IEvsEnumerator follow.
+Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb)  {
+    ALOGD("getCameraList");
+
+    const unsigned numCameras = mCameraList.size();
+
+    // Build up a packed array of CameraDesc for return
+    // NOTE:  Only has to live until the callback returns
+    std::vector<CameraDesc> descriptions;
+    descriptions.reserve(numCameras);
+    for (const auto& cam : mCameraList) {
+        descriptions.push_back( cam.pCamera->getDesc() );
+    }
+
+    // Encapsulate our camera descriptions in the HIDL vec type
+    hidl_vec<CameraDesc> hidlCameras(descriptions);
+
+    // Send back the results
+    ALOGD("reporting %zu cameras available", hidlCameras.size());
+    _hidl_cb(hidlCameras);
+
+    // HIDL convention says we return Void if we sent our result back via callback
+    return Void();
+}
+
+Return<void> EvsEnumerator::openCamera(const hidl_string& cameraId,
+                                             openCamera_cb callback) {
+    ALOGD("openCamera");
+
+    // Find the named camera
+    CameraRecord *pRecord = nullptr;
+    for (auto &&cam : mCameraList) {
+        if (cam.pCamera->getDesc().cameraId == cameraId) {
+            // Found a match!
+            pRecord = &cam;
+            break;
+        }
+    }
+
+    if (!pRecord) {
+        ALOGE("Requested camera %s not found", cameraId.c_str());
+        callback(nullptr);
+    }
+    else if (pRecord->inUse) {
+        ALOGE("Cannot open camera %s which is already in use", cameraId.c_str());
+        callback(nullptr);
+    }
+    else {
+        /* TODO(b/33492405):  Do this, When HIDL can give us back a recognizable pointer
+        pRecord->inUse = true;
+         */
+        callback(pRecord->pCamera);
+    }
+
+    return Void();
+}
+
+Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera>& camera) {
+    ALOGD("closeCamera");
+
+    if (camera == nullptr) {
+        ALOGE("Ignoring call to closeCamera with null camera pointer");
+    }
+    else {
+        // Make sure the camera has stopped streaming
+        camera->stopVideoStream();
+
+        /* TODO(b/33492405):  Do this, When HIDL can give us back a recognizable pointer
+        pRecord->inUse = false;
+         */
+    }
+
+    return Void();
+}
+
+Return<void> EvsEnumerator::openDisplay(openDisplay_cb callback) {
+    ALOGD("openDisplay");
+
+    // If we already have a display active, then this request must be denied
+    if (mActiveDisplay != nullptr) {
+        ALOGW("Rejecting openDisplay request the display is already in use.");
+        callback(nullptr);
+    }
+    else {
+        // Create a new display interface and return it
+        mActiveDisplay = new EvsDisplay();
+        ALOGD("Returning new EvsDisplay object %p", mActiveDisplay.get());
+        callback(mActiveDisplay);
+    }
+
+    return Void();
+}
+
+Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay>& display) {
+    ALOGD("closeDisplay");
+
+    if (mActiveDisplay == nullptr) {
+        ALOGE("Ignoring closeDisplay when display is not active");
+    }
+    else if (display == nullptr) {
+        ALOGE("Ignoring closeDisplay with null display pointer");
+    }
+    else {
+        // Drop the active display
+        // TODO(b/33492405):  When HIDL provides recognizable pointers, add validation here.
+        mActiveDisplay = nullptr;
+    }
+
+    return Void();
+}
+
+
+// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
+// As possible work around would be to give the client a HIDL object to exclusively hold
+// and use it's destructor to perform some work in the server side.
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
diff --git a/evs/1.0/default/EvsEnumerator.h b/evs/1.0/default/EvsEnumerator.h
new file mode 100644
index 0000000..69caa17
--- /dev/null
+++ b/evs/1.0/default/EvsEnumerator.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_EVS_V1_0_EVSCAMERAENUMERATOR_H
+#define ANDROID_HARDWARE_EVS_V1_0_EVSCAMERAENUMERATOR_H
+
+#include <android/hardware/evs/1.0/IEvsEnumerator.h>
+#include <android/hardware/evs/1.0/IEvsCamera.h>
+
+#include <list>
+
+#include "EvsCamera.h"
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+class EvsEnumerator : public IEvsEnumerator {
+public:
+    // Methods from ::android::hardware::evs::V1_0::IEvsEnumerator follow.
+    Return<void> getCameraList(getCameraList_cb _hidl_cb)  override;
+    Return<void> openCamera(const hidl_string& cameraId, openCamera_cb callback)  override;
+    Return<void> closeCamera(const ::android::sp<IEvsCamera>& carCamera)  override;
+    Return<void> openDisplay(openDisplay_cb callback)  override;
+    Return<void> closeDisplay(const ::android::sp<IEvsDisplay>& display)  override;
+
+    // Implementation details
+    EvsEnumerator();
+
+private:
+    struct CameraRecord {
+        sp<EvsCamera>   pCamera;
+        bool            inUse;
+        CameraRecord(EvsCamera* p, bool b) : pCamera(p), inUse(b) {}
+    };
+    std::list<CameraRecord> mCameraList;
+
+    sp<IEvsDisplay>         mActiveDisplay;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
+
+#endif  // ANDROID_HARDWARE_EVS_V1_0_EVSCAMERAENUMERATOR_H
diff --git a/evs/1.0/default/ServiceNames.h b/evs/1.0/default/ServiceNames.h
new file mode 100644
index 0000000..d20a37f
--- /dev/null
+++ b/evs/1.0/default/ServiceNames.h
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+const static char kEnumeratorServiceName[] = "EvsEnumeratorHw-Mock";
diff --git a/evs/1.0/default/android.hardware.evs@1.0-service.rc b/evs/1.0/default/android.hardware.evs@1.0-service.rc
new file mode 100644
index 0000000..be7c9f9
--- /dev/null
+++ b/evs/1.0/default/android.hardware.evs@1.0-service.rc
@@ -0,0 +1,4 @@
+service evs-hal-1-0 /system/bin/hw/android.hardware.evs@1.0-service
+    class hal
+    user cameraserver
+    group camera
diff --git a/evs/1.0/default/service.cpp b/evs/1.0/default/service.cpp
new file mode 100644
index 0000000..6ab2975
--- /dev/null
+++ b/evs/1.0/default/service.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.evs@1.0-service"
+
+#include <unistd.h>
+
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/Log.h>
+
+#include "ServiceNames.h"
+#include "EvsEnumerator.h"
+#include "EvsDisplay.h"
+
+
+// libhwbinder:
+using android::hardware::IPCThreadState;
+using android::hardware::ProcessState;
+
+// Generated HIDL files
+using android::hardware::evs::V1_0::IEvsEnumerator;
+using android::hardware::evs::V1_0::IEvsDisplay;
+
+// The namespace in which all our implementation code lives
+using namespace android::hardware::evs::V1_0::implementation;
+using namespace android;
+
+
+int main() {
+    ALOGI("EVS Hardware Enumerator service is starting");
+    android::sp<IEvsEnumerator> service = new EvsEnumerator();
+
+    // Register our service -- if somebody is already registered by our name,
+    // they will be killed (their thread pool will throw an exception).
+    status_t status = service->registerAsService(kEnumeratorServiceName);
+    if (status == OK) {
+        ALOGD("%s is ready.", kEnumeratorServiceName);
+
+        // Set thread pool size to ensure the API is not called in parallel.
+        // By setting the size to zero, the main thread will be the only one
+        // serving requests once we "joinThreadPool".
+        ProcessState::self()->setThreadPoolMaxThreadCount(0);
+
+        // Note:  We don't start the thread pool because it'll add at least one (default)
+        //        thread to it, which we don't want.  See b/31226656
+        // ProcessState::self()->startThreadPool();
+
+        // Send this main thread to become a permanent part of the thread pool.
+        // This bumps up the thread count by 1 (from zero in this case).
+        // This is not expected to return.
+        IPCThreadState::self()->joinThreadPool();
+    } else {
+        ALOGE("Could not register service %s (%d).", kEnumeratorServiceName, status);
+    }
+
+    // In normal operation, we don't expect the thread pool to exit
+    ALOGE("EVS Hardware Enumerator is shutting down");
+    return 1;
+}