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/Android.bp b/evs/1.0/Android.bp
new file mode 100644
index 0000000..86e9c1c
--- /dev/null
+++ b/evs/1.0/Android.bp
@@ -0,0 +1,80 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+ name: "android.hardware.evs@1.0_genc++",
+ tools: ["hidl-gen"],
+ cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.evs@1.0",
+ srcs: [
+ "types.hal",
+ "IEvsCamera.hal",
+ "IEvsCameraStream.hal",
+ "IEvsDisplay.hal",
+ "IEvsEnumerator.hal",
+ ],
+ out: [
+ "android/hardware/evs/1.0/types.cpp",
+ "android/hardware/evs/1.0/EvsCameraAll.cpp",
+ "android/hardware/evs/1.0/EvsCameraStreamAll.cpp",
+ "android/hardware/evs/1.0/EvsDisplayAll.cpp",
+ "android/hardware/evs/1.0/EvsEnumeratorAll.cpp",
+ ],
+}
+
+genrule {
+ name: "android.hardware.evs@1.0_genc++_headers",
+ tools: ["hidl-gen"],
+ cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.evs@1.0",
+ srcs: [
+ "types.hal",
+ "IEvsCamera.hal",
+ "IEvsCameraStream.hal",
+ "IEvsDisplay.hal",
+ "IEvsEnumerator.hal",
+ ],
+ out: [
+ "android/hardware/evs/1.0/types.h",
+ "android/hardware/evs/1.0/IEvsCamera.h",
+ "android/hardware/evs/1.0/IHwEvsCamera.h",
+ "android/hardware/evs/1.0/BnEvsCamera.h",
+ "android/hardware/evs/1.0/BpEvsCamera.h",
+ "android/hardware/evs/1.0/BsEvsCamera.h",
+ "android/hardware/evs/1.0/IEvsCameraStream.h",
+ "android/hardware/evs/1.0/IHwEvsCameraStream.h",
+ "android/hardware/evs/1.0/BnEvsCameraStream.h",
+ "android/hardware/evs/1.0/BpEvsCameraStream.h",
+ "android/hardware/evs/1.0/BsEvsCameraStream.h",
+ "android/hardware/evs/1.0/IEvsDisplay.h",
+ "android/hardware/evs/1.0/IHwEvsDisplay.h",
+ "android/hardware/evs/1.0/BnEvsDisplay.h",
+ "android/hardware/evs/1.0/BpEvsDisplay.h",
+ "android/hardware/evs/1.0/BsEvsDisplay.h",
+ "android/hardware/evs/1.0/IEvsEnumerator.h",
+ "android/hardware/evs/1.0/IHwEvsEnumerator.h",
+ "android/hardware/evs/1.0/BnEvsEnumerator.h",
+ "android/hardware/evs/1.0/BpEvsEnumerator.h",
+ "android/hardware/evs/1.0/BsEvsEnumerator.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.evs@1.0",
+ generated_sources: ["android.hardware.evs@1.0_genc++"],
+ generated_headers: ["android.hardware.evs@1.0_genc++_headers"],
+ export_generated_headers: ["android.hardware.evs@1.0_genc++_headers"],
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ "libcutils",
+ "android.hidl.base@1.0",
+ ],
+ export_shared_lib_headers: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "libutils",
+ "android.hidl.base@1.0",
+ ],
+}
diff --git a/evs/1.0/IEvsCamera.hal b/evs/1.0/IEvsCamera.hal
new file mode 100644
index 0000000..a2fc565
--- /dev/null
+++ b/evs/1.0/IEvsCamera.hal
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+import types;
+import IEvsCameraStream;
+
+
+/**
+ * Represents a single camera and is the primary interface for capturing images.
+ */
+interface IEvsCamera {
+
+ /**
+ * Returns the ID of this camera.
+ *
+ * Returns the string id of this camera. This must be the same value as reported in
+ * the camera_id field of the CameraDesc structure by EvsEnumerator::getCamerList().
+ */
+ getId() generates (string cameraId);
+
+ /**
+ * Specifies the depth of the buffer chain the camera is asked to support.
+ *
+ * Up to this many frames may be held concurrently by the client of IEvsCamera.
+ * If this many frames have been delivered to the receiver without being returned
+ * by doneWithFrame, the stream must skip frames until a buffer is returned for reuse.
+ * It is legal for this call to come at any time, even while streams are already running,
+ * in which case buffers should be added or removed from the chain as appropriate.
+ * If no call is made to this entry point, the IEvsCamera must support at least one
+ * frame by default. More is acceptable.
+ * BUFFER_NOT_AVAILABLE is returned if the implementation cannot support the
+ * requested number of concurrent frames.
+ */
+ setMaxFramesInFlight(uint32_t bufferCount) generates (EvsResult result);
+
+ /**
+ * Request delivery of EVS camera frames from this camera.
+ *
+ * The IEvsCameraStream must begin receiving periodic calls with new image
+ * frames until stopVideoStream() is called.
+ */
+ startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
+
+ /**
+ * Return a frame that was delivered by to the IEvsCameraStream.
+ *
+ * When done consuming a frame delivered to the IEvsCameraStream
+ * interface, it must be returned to the IEvsCamera for reuse.
+ * A small, finite number of buffers are available (possibly as small
+ * as one), and if the supply is exhausted, no further frames may be
+ * delivered until a buffer is returned.
+ */
+ doneWithFrame(uint32_t frameId, handle bufferHandle) generates (EvsResult result);
+
+ /**
+ * Stop the delivery of EVS camera frames.
+ *
+ * Because delivery is asynchronous, frames may continue to arrive for
+ * some time after this call returns. Each must be returned until the
+ * closure of the stream is signaled to the IEvsCameraStream.
+ * This function cannot fail and is simply ignored if the stream isn't running.
+ */
+ stopVideoStream();
+
+ /**
+ * Request driver specific information from the HAL implementation.
+ *
+ * The values allowed for opaqueIdentifier are driver specific,
+ * but no value passed in may crash the driver. The driver should
+ * return 0 for any unrecognized opaqueIdentifier.
+ */
+ getExtendedInfo(uint32_t opaqueIdentifier) generates (int32_t value);
+
+ /**
+ * Send a driver specific value to the HAL implementation.
+ *
+ * This extension is provided to facilitate car specific
+ * extensions, but no HAL implementation may require this call
+ * in order to function in a default state.
+ * INVALID_ARG is returned if the opaqueValue is not meaningful to
+ * the driver implementation.
+ */
+ setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue) generates (EvsResult result);
+};
diff --git a/evs/1.0/IEvsCameraStream.hal b/evs/1.0/IEvsCameraStream.hal
new file mode 100644
index 0000000..ef5460f
--- /dev/null
+++ b/evs/1.0/IEvsCameraStream.hal
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+
+/**
+ * Implemented on client side to receive asynchronous video frame deliveries.
+ */
+interface IEvsCameraStream {
+
+ /**
+ * Receives calls from the HAL each time a video frame is ready for inspection.
+ * Buffer handles received by this method must be returned via calls to
+ * IEvsCamera::doneWithFrame(). When the video stream is stopped via a call
+ * to IEvsCamera::stopVideoStream(), this callback may continue to happen for
+ * some time as the pipeline drains. Each frame must still be returned.
+ * When the last frame in the stream has been delivered, a NULL bufferHandle
+ * must be delivered, signifying the end of the stream. No further frame
+ * deliveries may happen thereafter.
+ */
+ oneway deliverFrame(uint32_t frameId, handle bufferHandle);
+};
diff --git a/evs/1.0/IEvsDisplay.hal b/evs/1.0/IEvsDisplay.hal
new file mode 100644
index 0000000..a473872
--- /dev/null
+++ b/evs/1.0/IEvsDisplay.hal
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+import types;
+
+
+/**
+ * Represents a single camera and is the primary interface for capturing images.
+ */
+interface IEvsDisplay {
+
+ /**
+ * Returns basic information about the EVS display provided by the system.
+ *
+ * See the description of the DisplayDesc structure below for details.
+ */
+ getDisplayInfo() generates (DisplayDesc info);
+
+
+ /**
+ * 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 defer or 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.
+ * Returns INVALID_ARG if the requested state is not a recognized value.
+ */
+ setDisplayState(DisplayState state) generates (EvsResult result);
+
+
+ /**
+ * This call requests the current state of the display
+ *
+ * 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.
+ */
+ getDisplayState() generates (DisplayState state);
+
+
+ /**
+ * This call returns a handle to a frame buffer associated with the display.
+ *
+ * The returned 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.
+ */
+ getTargetBuffer() generates (handle bufferHandle);
+
+
+ /**
+ * 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.
+ * There is no maximum time the caller may hold onto the buffer before making this
+ * call. The buffer may be returned at any time and in any DisplayState, but all
+ * buffers are expected to be returned before the IEvsDisplay interface is destroyed.
+ */
+ returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);
+};
diff --git a/evs/1.0/IEvsEnumerator.hal b/evs/1.0/IEvsEnumerator.hal
new file mode 100644
index 0000000..e3a1382
--- /dev/null
+++ b/evs/1.0/IEvsEnumerator.hal
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+import types;
+import IEvsCamera;
+import IEvsDisplay;
+
+
+/**
+ * Provides the mechanism for EVS camera discovery
+ */
+interface IEvsEnumerator {
+
+ /**
+ * Returns a list of all EVS cameras available to the system
+ */
+ getCameraList() generates (vec<CameraDesc> cameras);
+
+
+ /**
+ * Get the IEvsCamera associated with a cameraId from a CameraDesc
+ *
+ * Given a camera's unique cameraId from ca CameraDesc, returns
+ * the ICamera interface assocaited with the specified camera.
+ * When done using the camera, it must be returned by calling
+ * closeCamera on the ICamera interface.
+ */
+ openCamera(string cameraId) generates (IEvsCamera carCamera);
+
+ /**
+ * Return the specified IEvsCamera interface as no longer in use
+ *
+ * When the IEvsCamera object is no longer required, it must be released.
+ * NOTE: Video streaming must be cleanly stopped before making this call.
+ */
+ closeCamera(IEvsCamera carCamera);
+
+
+ /**
+ * Get exclusive access to IEvsDisplay for the system
+ *
+ * There can be at most one EVS display object for the system and this function
+ * requests access to it. If the EVS display is not available or is already in use,
+ * a null pointer is returned.
+ */
+ openDisplay() generates (IEvsDisplay display);
+
+ /**
+ * Return the specified IEvsDisplay interface as no longer in use
+ *
+ * When the IEvsDisplay object is no longer required, it must be released.
+ * NOTE: All buffer must have been returned to the display before making this call.
+ */
+ closeDisplay(IEvsDisplay display);
+};
+
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;
+}
diff --git a/evs/1.0/types.hal b/evs/1.0/types.hal
new file mode 100644
index 0000000..e0051e1
--- /dev/null
+++ b/evs/1.0/types.hal
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+
+/*
+ * Bit flags indicating suggested uses for a given EVS camera
+ *
+ * The values in the UsageHint bit field provide a generic expression of how a
+ * given camera is intended to be used. The values for these flags support
+ * existing use cases, and are used by the default EVS application to select
+ * appropriate cameras for display based on observed vehicle state (such as
+ * turn signal activation or selection of reverse gear). When implementing
+ * their own specialized EVS Applications, OEMs are free to use these flags
+ * and/or the opaque vendor_flags to drive their own vehicle specific logic.
+ */
+enum UsageHint : uint32_t {
+ USAGE_HINT_REVERSE = 0x00000001,
+ USAGE_HINT_LEFT_TURN = 0x00000002,
+ USAGE_HINT_RIGHT_TURN = 0x00000004,
+ // remaining bits are reserved for future use
+};
+
+
+/*
+ * Structure describing the basic properties of an EVS camera
+ *
+ * The HAL is responsible for filling out this structure for each
+ * EVS camera in the system. Attention should be given to the field
+ * of view, direction of view, and location parameters as these may
+ * be used to (if available) to project overlay graphics into the
+ * scene by an EVS application.
+ * Any of these values for which the HAL does not have reasonable values
+ * should be set to ZERO.
+ */
+struct CameraDesc {
+ string cameraId;
+ UsageHint hints; // Bit flags (legal to | values together) (TODO: b/31702236)
+ uint32_t vendorFlags; // Opaque value from driver
+ uint32_t defaultHorResolution; // Units of pixels
+ uint32_t defaultVerResolution; // Units of pixels
+};
+
+
+/*
+ * Structure describing the basic properties of an EVS display
+ *
+ * The HAL is responsible for filling out this structure to describe
+ * the EVS display. As an implementation detail, this may be a physical
+ * display or a virtual display that is overlaid or mixed with another
+ * presentation device.
+ */
+struct DisplayDesc {
+ string displayId;
+ uint32_t vendorFlags; // Opaque value from driver
+ uint32_t defaultHorResolution; // Units of pixels
+ uint32_t defaultVerResolution; // Units of pixels
+};
+
+
+/*
+ * States for control of the EVS display
+ *
+ * The DisplayInfo structure describes the basic properties of an EVS display. Any EVS
+ * implementation is required to have one. The HAL is responsible for filling out this
+ * structure to describe the EVS display. As an implementation detail, this may be a
+ * physical display or a virtual display that is overlaid or mixed with another
+ * presentation device.
+ */
+enum DisplayState : uint32_t {
+ NOT_VISIBLE = 0, // Display is inhibited
+ VISIBLE_ON_NEXT_FRAME, // Will become visible with next frame
+ VISIBLE, // Display is currently active
+ NUM_STATES // Must be last
+};
+
+
+/* Error codes used in EVS HAL interface. */
+/* TODO: Adopt a common set of function return codes */
+enum EvsResult : uint32_t {
+ OK = 0,
+ INVALID_ARG,
+ STREAM_ALREADY_RUNNING,
+ BUFFER_NOT_AVAILABLE,
+};
\ No newline at end of file