Find V4L2 devices from /dev/video*.
Since V4L2CameraHAL now populates its list of cameras,
also added a necessary piece of metadata that was
causing cameraservice to crash.
BUG: 29160300
TEST: Ran on rpi3. HAL finds dev/video* nodes. When a
sym link (/dev/video5 -> /dev/video0) was added, the HAL
correctly did not add a 3rd device.
Change-Id: I95656ac9c062b193c12712b1c73e888bf1f1a961
diff --git a/modules/camera/3_4/V4L2Camera.cpp b/modules/camera/3_4/V4L2Camera.cpp
index 1529756..aa65cdf 100644
--- a/modules/camera/3_4/V4L2Camera.cpp
+++ b/modules/camera/3_4/V4L2Camera.cpp
@@ -37,6 +37,9 @@
android::CameraMetadata metadata(1);
// TODO(b/29214516): fill this in.
+ uint8_t scene_mode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
+ metadata.update(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &scene_mode, 1);
+
return metadata.release();
}
diff --git a/modules/camera/3_4/V4L2CameraHAL.cpp b/modules/camera/3_4/V4L2CameraHAL.cpp
index ad5fbde..ec99a4c 100644
--- a/modules/camera/3_4/V4L2CameraHAL.cpp
+++ b/modules/camera/3_4/V4L2CameraHAL.cpp
@@ -18,7 +18,17 @@
#include "V4L2CameraHAL.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <linux/videodev2.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <algorithm>
#include <cstdlib>
+#include <unordered_set>
#include "Common.h"
#include "V4L2Camera.h"
@@ -54,7 +64,57 @@
V4L2CameraHAL::V4L2CameraHAL() : mCameras(), mCallbacks(NULL) {
HAL_LOG_ENTER();
- // TODO(29160300): Populate camera devices.
+ // Adds all available V4L2 devices.
+ // List /dev nodes.
+ DIR* dir = opendir("/dev");
+ if (dir == NULL) {
+ HAL_LOGE("Failed to open /dev");
+ return;
+ }
+ // Find /dev/video* nodes.
+ dirent* ent;
+ std::vector<std::string> nodes;
+ while ((ent = readdir(dir))) {
+ std::string desired = "video";
+ size_t len = desired.size();
+ if (strncmp(desired.c_str(), ent->d_name, len) == 0) {
+ if (strlen(ent->d_name) > len && isdigit(ent->d_name[len])) {
+ // ent is a numbered video node.
+ nodes.push_back(std::string("/dev/") + ent->d_name);
+ HAL_LOGV("Found video node %s.", nodes.back().c_str());
+ }
+ }
+ }
+ // Test each for V4L2 support and uniqueness.
+ std::unordered_set<std::string> buses;
+ std::string bus;
+ v4l2_capability cap;
+ int fd;
+ int id = 0;
+ for (const auto& node : nodes) {
+ // Open the node.
+ fd = TEMP_FAILURE_RETRY(open(node.c_str(), O_RDWR));
+ if (fd < 0) {
+ HAL_LOGE("failed to open %s (%s).", node.c_str(), strerror(errno));
+ continue;
+ }
+ // Read V4L2 capabilities.
+ if (TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_QUERYCAP, &cap)) != 0) {
+ HAL_LOGE("VIDIOC_QUERYCAP on %s fail: %s.", node.c_str(),
+ strerror(errno));
+ } else if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+ HAL_LOGE("%s is not a V4L2 video capture device.", node.c_str());
+ } else {
+ // If the node is unique, add a camera for it.
+ bus = reinterpret_cast<char*>(cap.bus_info);
+ if (buses.insert(bus).second) {
+ HAL_LOGV("Found unique bus at %s.", node.c_str());
+ std::unique_ptr<V4L2Camera> cam(new V4L2Camera(id++, node));
+ mCameras.push_back(std::move(cam));
+ }
+ }
+ TEMP_FAILURE_RETRY(close(fd));
+ }
}
V4L2CameraHAL::~V4L2CameraHAL() {
@@ -101,8 +161,8 @@
return -ENOSYS;
}
-int V4L2CameraHAL::open(const hw_module_t* module, const char* name,
- hw_device_t** device) {
+int V4L2CameraHAL::openDevice(const hw_module_t* module, const char* name,
+ hw_device_t** device) {
HAL_LOG_ENTER();
if (module != &HAL_MODULE_INFO_SYM.common) {
@@ -153,7 +213,7 @@
static int open_dev(const hw_module_t* module, const char* name,
hw_device_t** device) {
- return gCameraHAL.open(module, name, device);
+ return gCameraHAL.openDevice(module, name, device);
}
} // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/V4L2CameraHAL.h b/modules/camera/3_4/V4L2CameraHAL.h
index 858ad32..55d84c9 100644
--- a/modules/camera/3_4/V4L2CameraHAL.h
+++ b/modules/camera/3_4/V4L2CameraHAL.h
@@ -48,7 +48,7 @@
int setTorchMode(const char* camera_id, bool enabled);
// Hardware Module Interface (see <hardware/hardware.h>).
- int open(const hw_module_t* mod, const char* name, hw_device_t** dev);
+ int openDevice(const hw_module_t* mod, const char* name, hw_device_t** dev);
private:
// Vector of cameras.