Refactor camera initialization support of gralloc.

Switch to a factory model so that initialization can
fail when the gralloc module can't be found or isn't supported.

BUG: 30140438
Change-Id: I6e0a62a207797aef96c532cff7632c1a4da8818f
This commit is contained in:
Ari Hausman-Cohen 2016-07-21 16:28:17 -07:00
parent 24e541c925
commit 681eaa283f
5 changed files with 70 additions and 45 deletions

View file

@ -47,9 +47,23 @@ static std::vector<int32_t> getMetadataKeys(
return keys;
}
V4L2Camera::V4L2Camera(int id, std::string path)
V4L2Camera* V4L2Camera::NewV4L2Camera(int id, const std::string path) {
HAL_LOG_ENTER();
std::unique_ptr<V4L2Gralloc> gralloc(V4L2Gralloc::NewV4L2Gralloc());
if (!gralloc) {
HAL_LOGE("Failed to initialize gralloc helper.");
return nullptr;
}
return new V4L2Camera(id, path, std::move(gralloc));
}
V4L2Camera::V4L2Camera(int id, std::string path,
std::unique_ptr<V4L2Gralloc> gralloc)
: default_camera_hal::Camera(id),
mDevicePath(std::move(path)),
mGralloc(std::move(gralloc)),
mOutStreamType(0),
mOutStreamFormat(0),
mOutStreamWidth(0),
@ -753,21 +767,6 @@ int V4L2Camera::initDevice() {
HAL_LOG_ENTER();
int res;
// Initialize and check the gralloc module.
const hw_module_t* module;
res = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (res) {
HAL_LOGE("Couldn't get gralloc module.");
return -ENODEV;
}
const gralloc_module_t* gralloc =
reinterpret_cast<const gralloc_module_t*>(module);
mGralloc = V4L2Gralloc(gralloc);
if (!mGralloc.isValid()) {
HAL_LOGE("Invalid gralloc module.");
return -ENODEV;
}
// Templates should be set up if they haven't already been.
if (!mTemplatesInitialized) {
res = initTemplates();
@ -800,14 +799,14 @@ int V4L2Camera::enqueueBuffer(const camera3_stream_buffer_t* camera_buffer) {
// queue length.
device_buffer.index = 0;
// Lock the buffer for writing.
int res = mGralloc.lock(camera_buffer, mOutStreamBytesPerLine,
int res = mGralloc->lock(camera_buffer, mOutStreamBytesPerLine,
&device_buffer);
if (res) {
return res;
}
if (ioctlLocked(VIDIOC_QBUF, &device_buffer) < 0) {
HAL_LOGE("QBUF (%d) fails: %s", 0, strerror(errno));
mGralloc.unlock(&device_buffer);
mGralloc->unlock(&device_buffer);
return -ENODEV;
}
@ -817,7 +816,7 @@ int V4L2Camera::enqueueBuffer(const camera3_stream_buffer_t* camera_buffer) {
// turned off before another call to this function).
res = streamOn();
if (res) {
mGralloc.unlock(&device_buffer);
mGralloc->unlock(&device_buffer);
return res;
}
@ -828,11 +827,11 @@ int V4L2Camera::enqueueBuffer(const camera3_stream_buffer_t* camera_buffer) {
v4l2_buffer result_buffer;
res = dequeueBuffer(&result_buffer);
if (res) {
mGralloc.unlock(&result_buffer);
mGralloc->unlock(&result_buffer);
return res;
}
// Now that we're done painting the buffer, we can unlock it.
res = mGralloc.unlock(&result_buffer);
res = mGralloc->unlock(&result_buffer);
if (res) {
return res;
}

View file

@ -38,10 +38,17 @@ namespace v4l2_camera_hal {
// metadata and logic about that device.
class V4L2Camera : public default_camera_hal::Camera {
public:
V4L2Camera(int id, const std::string path);
// Use this method to create V4L2Camera objects. Functionally equivalent
// to "new V4L2Camera", except that it may return nullptr in case of failure.
static V4L2Camera* NewV4L2Camera(int id, const std::string path);
~V4L2Camera();
private:
// Constructor private to allow failing on bad input.
// Use NewV4L2Camera instead.
V4L2Camera(int id, const std::string path,
std::unique_ptr<V4L2Gralloc> gralloc);
// default_camera_hal::Camera virtual methods.
// Connect to the device: open dev nodes, etc.
int connect() override;
@ -86,7 +93,7 @@ private:
// The opened device fd.
ScopedFd mDeviceFd;
// Gralloc helper.
V4L2Gralloc mGralloc;
std::unique_ptr<V4L2Gralloc> mGralloc;
// Lock protecting use of the device.
android::Mutex mDeviceLock;
// Wrapper around ioctl.

View file

@ -95,8 +95,12 @@ V4L2CameraHAL::V4L2CameraHAL() : mCameras(), mCallbacks(NULL) {
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));
std::unique_ptr<V4L2Camera> cam(V4L2Camera::NewV4L2Camera(id++, node));
if (cam) {
mCameras.push_back(std::move(cam));
} else {
HAL_LOGE("Failed to initialize camera at %s.", node.c_str());
}
}
}
TEMP_FAILURE_RETRY(close(fd));

View file

@ -46,6 +46,33 @@ void copyWithPadding(uint8_t* dest, const uint8_t* src, size_t dest_stride,
}
}
V4L2Gralloc* V4L2Gralloc::NewV4L2Gralloc() {
HAL_LOG_ENTER();
// Initialize and check the gralloc module.
const hw_module_t* module = nullptr;
int res = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (res || !module) {
HAL_LOGE("Couldn't get gralloc module.");
return nullptr;
}
const gralloc_module_t* gralloc =
reinterpret_cast<const gralloc_module_t*>(module);
// This class only supports Gralloc v0, not Gralloc V1.
if (gralloc->common.module_api_version > GRALLOC_MODULE_API_VERSION_0_3) {
HAL_LOGE("Invalid gralloc version %x. Only 0.3 (%x) "
"and below are supported by this HAL.",
gralloc->common.module_api_version,
GRALLOC_MODULE_API_VERSION_0_3);
return nullptr;
}
return new V4L2Gralloc(gralloc);
}
// Private. As checked by above factory, module will be non-null
// and a supported version.
V4L2Gralloc::V4L2Gralloc(const gralloc_module_t* module)
: mModule(module) {
HAL_LOG_ENTER();
@ -65,21 +92,6 @@ V4L2Gralloc::~V4L2Gralloc() {
}
}
bool V4L2Gralloc::isValid() {
HAL_LOG_ENTER();
// This helper only supports Gralloc v0, not Gralloc V1.
if (mModule->common.module_api_version > GRALLOC_MODULE_API_VERSION_0_3) {
HAL_LOGE("Invalid gralloc version %x. Only 0.3 (%x) "
"and below are supported by this HAL.",
mModule->common.module_api_version,
GRALLOC_MODULE_API_VERSION_0_3);
return false;
}
return true;
}
int V4L2Gralloc::lock(const camera3_stream_buffer_t* camera_buffer,
uint32_t bytes_per_line,
/*out*/ v4l2_buffer* device_buffer) {

View file

@ -34,8 +34,10 @@ static constexpr size_t V4L2_MAX_JPEG_SIZE = 3000000;
// with some assistive transformations.
class V4L2Gralloc {
public:
V4L2Gralloc(const gralloc_module_t* module = nullptr);
~V4L2Gralloc();
// Use this method to create V4L2Gralloc objects. Functionally equivalent
// to "new V4L2Gralloc", except that it may return nullptr in case of failure.
static V4L2Gralloc* NewV4L2Gralloc();
virtual ~V4L2Gralloc();
// Lock a camera buffer. Sets device buffer user pointer and length.
int lock(const camera3_stream_buffer_t* camera_buffer,
@ -45,10 +47,11 @@ public:
// based on buffer user pointer, not the specific object).
int unlock(const v4l2_buffer* device_buffer);
// Check that the module passed in to the constructor is supported.
bool isValid();
private:
// Constructor is private to allow failing on bad input.
// Use NewV4L2Gralloc instead.
V4L2Gralloc(const gralloc_module_t* module);
const gralloc_module_t* mModule;
struct BufferData {