aboutsummaryrefslogtreecommitdiff
path: root/evs/sampleDriver/EvsEnumerator.cpp
diff options
context:
space:
mode:
authorScott Randolph <randolphs@google.com>2017-04-25 17:38:29 -0700
committerScott Randolph <randolphs@google.com>2017-05-02 16:47:36 -0700
commitb342cb163393317d8af77339ff8ff5e921bd4a8f (patch)
treeb5807ef0bbe3d37db0b7337dd267707abc5c6b3f /evs/sampleDriver/EvsEnumerator.cpp
parentfd519152b4ca81a8635c3c94c8c1c4e5d0021719 (diff)
downloadCar-b342cb163393317d8af77339ff8ff5e921bd4a8f.tar.gz
V4L2 & Surface Flinger based EVS driver
This provides a functional driver, although not suitable for use at early boot because of the SurfaceFlinger dependency. This is enough to get a demo application running, however, and to illustrate the necessary behaviors. Test: Build and run against evs_app Change-Id: I5492a7818018319bdf7e00f147d387e14acf4993
Diffstat (limited to 'evs/sampleDriver/EvsEnumerator.cpp')
-rw-r--r--evs/sampleDriver/EvsEnumerator.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/evs/sampleDriver/EvsEnumerator.cpp b/evs/sampleDriver/EvsEnumerator.cpp
new file mode 100644
index 0000000000..9682450469
--- /dev/null
+++ b/evs/sampleDriver/EvsEnumerator.cpp
@@ -0,0 +1,211 @@
+/*
+ * 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.automotive.evs@1.0-display"
+
+#include "EvsEnumerator.h"
+#include "EvsV4lCamera.h"
+#include "EvsGlDisplay.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+
+// NOTE: All members values are static so that all clients operate on the same state
+// That is to say, this is effectively a singleton despite the fact that HIDL
+// constructs a new instance for each client.
+std::list<EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
+wp<EvsGlDisplay> EvsEnumerator::sActiveDisplay;
+
+
+EvsEnumerator::EvsEnumerator() {
+ ALOGD("EvsEnumerator created");
+
+ // Hardwired for now.
+ // We could walk and query all devices matching /dev/video* but that would take some time,
+ // especially if any devices time out. Perhaps best if each platform populates this with
+ // their set of known values.
+ sCameraList.emplace_back("/dev/video0");
+}
+
+
+// Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
+Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) {
+ ALOGD("getCameraList");
+
+ const unsigned numCameras = sCameraList.size();
+
+ // Build up a packed array of CameraDesc for return
+ hidl_vec<CameraDesc> hidlCameras;
+ hidlCameras.resize(numCameras);
+ unsigned i = 0;
+ for (const auto& cam : sCameraList) {
+ hidlCameras[i++] = cam.desc;
+ }
+
+ // 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<sp<IEvsCamera>> EvsEnumerator::openCamera(const hidl_string& cameraId) {
+ ALOGD("openCamera");
+
+ // Is this a recognized camera id?
+ CameraRecord *pRecord = findCameraById(cameraId);
+ if (!pRecord) {
+ ALOGE("Requested camera %s not found", cameraId.c_str());
+ return nullptr;
+ }
+
+ // Has this camera already been instantiated by another caller?
+ sp<EvsV4lCamera> pActiveCamera = pRecord->activeInstance.promote();
+ if (pActiveCamera != nullptr) {
+ ALOGW("Killing previous camera because of new caller");
+ closeCamera(pActiveCamera);
+ }
+
+ // Construct a camera instance for the caller
+ pActiveCamera = new EvsV4lCamera(cameraId.c_str());
+ pRecord->activeInstance = pActiveCamera;
+ if (pActiveCamera == nullptr) {
+ ALOGE("Failed to allocate new EvsV4lCamera object for %s\n", cameraId.c_str());
+ }
+
+ return pActiveCamera;
+}
+
+
+Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera>& pCamera) {
+ ALOGD("closeCamera");
+
+ if (pCamera == nullptr) {
+ ALOGE("Ignoring call to closeCamera with null camera ptr");
+ return Void();
+ }
+
+ // Get the camera id so we can find it in our list
+ std::string cameraId;
+ pCamera->getCameraInfo([&cameraId](CameraDesc desc) {
+ cameraId = desc.cameraId;
+ }
+ );
+
+ // Find the named camera
+ CameraRecord *pRecord = findCameraById(cameraId);
+
+ // Is the display being destroyed actually the one we think is active?
+ if (!pRecord) {
+ ALOGE("Asked to close a camera whose name isn't recognized");
+ } else {
+ sp<EvsV4lCamera> pActiveCamera = pRecord->activeInstance.promote();
+
+ if (pActiveCamera == nullptr) {
+ ALOGE("Somehow a camera is being destroyed when the enumerator didn't know one existed");
+ } else if (pActiveCamera != pCamera) {
+ // This can happen if the camera was aggressively reopened, orphaning this previous instance
+ ALOGW("Ignoring close of previously orphaned camera - why did a client steal?");
+ } else {
+ // Drop the active camera
+ pActiveCamera->shutdown();
+ pRecord->activeInstance = nullptr;
+ }
+ }
+
+ return Void();
+}
+
+
+Return<sp<IEvsDisplay>> EvsEnumerator::openDisplay() {
+ ALOGD("openDisplay");
+
+ // If we already have a display active, then we need to shut it down so we can
+ // give exclusive access to the new caller.
+ sp<EvsGlDisplay> pActiveDisplay = sActiveDisplay.promote();
+ if (pActiveDisplay != nullptr) {
+ ALOGW("Killing previous display because of new caller");
+ closeDisplay(pActiveDisplay);
+ }
+
+ // Create a new display interface and return it
+ pActiveDisplay = new EvsGlDisplay();
+ sActiveDisplay = pActiveDisplay;
+
+ ALOGD("Returning new EvsGlDisplay object %p", pActiveDisplay.get());
+ return pActiveDisplay;
+}
+
+
+Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay>& pDisplay) {
+ ALOGD("closeDisplay");
+
+ // Do we still have a display object we think should be active?
+ sp<EvsGlDisplay> pActiveDisplay = sActiveDisplay.promote();
+ if (pActiveDisplay == nullptr) {
+ ALOGE("Somehow a display is being destroyed when the enumerator didn't know one existed");
+ } else if (sActiveDisplay != pDisplay) {
+ ALOGW("Ignoring close of previously orphaned display - why did a client steal?");
+ } else {
+ // Drop the active display
+ pActiveDisplay->forceShutdown();
+ sActiveDisplay = nullptr;
+ }
+
+ return Void();
+}
+
+
+Return<DisplayState> EvsEnumerator::getDisplayState() {
+ ALOGD("getDisplayState");
+
+ // Do we still have a display object we think should be active?
+ sp<IEvsDisplay> pActiveDisplay = sActiveDisplay.promote();
+ if (pActiveDisplay != nullptr) {
+ return pActiveDisplay->getDisplayState();
+ } else {
+ return DisplayState::NOT_OPEN;
+ }
+}
+
+
+EvsEnumerator::CameraRecord* EvsEnumerator::findCameraById(const std::string& cameraId) {
+ // Find the named camera
+ for (auto &&cam : sCameraList) {
+ if (cam.desc.cameraId == cameraId) {
+ // Found a match!
+ return &cam;
+ }
+ }
+
+ // We didn't find a match
+ return nullptr;
+}
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace automotive
+} // namespace hardware
+} // namespace android