Open and close v4l2 devices.
BUG: 29191881
Change-Id: Id740ab30fd8f79b4a2cb99d1e5bef2be7472c992
diff --git a/modules/camera/3_4/Android.mk b/modules/camera/3_4/Android.mk
index b3b921f..074f9c2 100644
--- a/modules/camera/3_4/Android.mk
+++ b/modules/camera/3_4/Android.mk
@@ -26,10 +26,12 @@
# some various unexpected variables had to be set.
LOCAL_SHARED_LIBRARIES := \
+ libbase \
libcamera_client \
libcamera_metadata \
libcutils \
liblog \
+ libnativehelper \
libsync \
libutils \
diff --git a/modules/camera/3_4/Camera.cpp b/modules/camera/3_4/Camera.cpp
index b18f0c3..6e9e12a 100644
--- a/modules/camera/3_4/Camera.cpp
+++ b/modules/camera/3_4/Camera.cpp
@@ -81,7 +81,7 @@
}
}
-int Camera::open(const hw_module_t *module, hw_device_t **device)
+int Camera::openDevice(const hw_module_t *module, hw_device_t **device)
{
ALOGI("%s:%d: Opening camera device", __func__, mId);
ATRACE_CALL();
@@ -92,7 +92,10 @@
return -EBUSY;
}
- // TODO: open camera dev nodes, etc
+ int connectResult = connect();
+ if (connectResult != 0) {
+ return connectResult;
+ }
mBusy = true;
mDevice.common.module = const_cast<hw_module_t*>(module);
*device = &mDevice.common;
@@ -124,7 +127,7 @@
return -EINVAL;
}
- // TODO: close camera dev nodes, etc
+ disconnect();
mBusy = false;
return 0;
}
diff --git a/modules/camera/3_4/Camera.h b/modules/camera/3_4/Camera.h
index ab8f221..3ecd0a8 100644
--- a/modules/camera/3_4/Camera.h
+++ b/modules/camera/3_4/Camera.h
@@ -40,7 +40,7 @@
virtual ~Camera();
// Common Camera Device Operations (see <hardware/camera_common.h>)
- int open(const hw_module_t *module, hw_device_t **device);
+ int openDevice(const hw_module_t *module, hw_device_t **device);
int getInfo(struct camera_info *info);
int close();
@@ -54,6 +54,10 @@
protected:
+ // Connect to the device: open dev nodes, etc.
+ virtual int connect() = 0;
+ // Disconnect from the device: close dev nodes, etc.
+ virtual void disconnect() = 0;
// Initialize static camera characteristics for individual device
virtual camera_metadata_t *initStaticInfo() = 0;
// Initialize device info: facing, orientation, resource cost,
diff --git a/modules/camera/3_4/V4L2Camera.cpp b/modules/camera/3_4/V4L2Camera.cpp
index aa65cdf..5e5c0c4 100644
--- a/modules/camera/3_4/V4L2Camera.cpp
+++ b/modules/camera/3_4/V4L2Camera.cpp
@@ -16,8 +16,13 @@
#include "V4L2Camera.h"
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
#include <camera/CameraMetadata.h>
#include <hardware/camera3.h>
+#include <nativehelper/ScopedFd.h>
#include "Common.h"
@@ -32,6 +37,35 @@
HAL_LOG_ENTER();
}
+int V4L2Camera::connect() {
+ HAL_LOG_ENTER();
+
+ if (mDeviceFd.get() >= 0) {
+ HAL_LOGE("Camera device %s is opened. Close it first", mDevicePath.c_str());
+ return -EIO;
+ }
+
+ int fd = TEMP_FAILURE_RETRY(open(mDevicePath.c_str(), O_RDWR));
+ if (fd < 0) {
+ HAL_LOGE("failed to open %s (%s)", mDevicePath.c_str(), strerror(errno));
+ return -errno;
+ }
+ mDeviceFd.reset(fd);
+
+ // TODO(b/29185945): confirm this is a supported device.
+ // This is checked by the HAL, but the device at mDevicePath may
+ // not be the same one that was there when the HAL was loaded.
+ // (Alternatively, better hotplugging support may make this unecessary
+ // by disabling cameras that get disconnected and checking newly connected
+ // cameras, so connect() is never called on an unsupported camera)
+ return 0;
+}
+
+void V4L2Camera::disconnect() {
+ HAL_LOG_ENTER();
+ mDeviceFd.reset();
+}
+
camera_metadata_t* V4L2Camera::initStaticInfo() {
HAL_LOG_ENTER();
diff --git a/modules/camera/3_4/V4L2Camera.h b/modules/camera/3_4/V4L2Camera.h
index 4ac9cc4..4cc0103 100644
--- a/modules/camera/3_4/V4L2Camera.h
+++ b/modules/camera/3_4/V4L2Camera.h
@@ -21,7 +21,9 @@
#include <string>
+#include <nativehelper/ScopedFd.h>
#include <system/camera_metadata.h>
+
#include "Camera.h"
#include "Common.h"
@@ -37,6 +39,10 @@
private:
// default_camera_hal::Camera virtual methods.
+ // Connect to the device: open dev nodes, etc.
+ int connect();
+ // Disconnect from the device: close dev nodes, etc.
+ void disconnect();
// Initialize static camera characteristics for individual device.
camera_metadata_t *initStaticInfo();
// Initialize device info: facing, orientation, resource cost,
@@ -49,6 +55,8 @@
// The camera device path. For example, /dev/video0.
const std::string mDevicePath;
+ // The opened device fd.
+ ScopedFd mDeviceFd;
DISALLOW_COPY_AND_ASSIGN(V4L2Camera);
};
diff --git a/modules/camera/3_4/V4L2CameraHAL.cpp b/modules/camera/3_4/V4L2CameraHAL.cpp
index ec99a4c..6696ba5 100644
--- a/modules/camera/3_4/V4L2CameraHAL.cpp
+++ b/modules/camera/3_4/V4L2CameraHAL.cpp
@@ -30,6 +30,8 @@
#include <cstdlib>
#include <unordered_set>
+#include <android-base/parseint.h>
+
#include "Common.h"
#include "V4L2Camera.h"
@@ -46,22 +48,6 @@
// Default global camera hal.
static V4L2CameraHAL gCameraHAL;
-// Helper function for converting and validating string name to int id.
-// Returns either a non-negative camera id, or a negative error code.
-static int id_from_name(const char* name) {
- if (name == NULL || *name == '\0') {
- HAL_LOGE("Invalid camera id name is NULL");
- return -EINVAL;
- }
- char* nameEnd;
- int id = strtol(name, &nameEnd, 10);
- if (*nameEnd != '\0' || id < 0) {
- HAL_LOGE("Invalid camera id name %s", name);
- return -EINVAL;
- }
- return id;
-}
-
V4L2CameraHAL::V4L2CameraHAL() : mCameras(), mCallbacks(NULL) {
HAL_LOG_ENTER();
// Adds all available V4L2 devices.
@@ -171,14 +157,12 @@
return -EINVAL;
}
- int id = id_from_name(name);
- if (id < 0) {
- return id;
- } else if (id < 0 || id >= mCameras.size()) {
+ int id;
+ if (!android::base::ParseInt(name, &id, 0, getNumberOfCameras() - 1)) {
return -EINVAL;
}
// TODO(b/29185945): Hotplugging: return -EINVAL if unplugged.
- return mCameras[id]->open(module, device);
+ return mCameras[id]->openDevice(module, device);
}
/*