diff options
author | Scott Randolph <randolphs@google.com> | 2017-04-25 17:38:29 -0700 |
---|---|---|
committer | Scott Randolph <randolphs@google.com> | 2017-05-02 16:47:36 -0700 |
commit | b342cb163393317d8af77339ff8ff5e921bd4a8f (patch) | |
tree | b5807ef0bbe3d37db0b7337dd267707abc5c6b3f /evs/sampleDriver/EvsEnumerator.cpp | |
parent | fd519152b4ca81a8635c3c94c8c1c4e5d0021719 (diff) | |
download | Car-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.cpp | 211 |
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 |