V4L2 HALv3 initial check in

Decent outline of an initial HALv3. Still a lot to be filled in.
Adapted from the reference implementation in libhardware.

BUG: 29006356
TEST: Ran simple test program. Connects to the HAL and then
  fails because there are no cameras (expected behavior right now).

Change-Id: I11c7e00dca1bbb6ade6b5a0f55fedac3d2d01695
diff --git a/modules/camera/3_4/V4L2CameraHAL.cpp b/modules/camera/3_4/V4L2CameraHAL.cpp
new file mode 100644
index 0000000..511d8a1
--- /dev/null
+++ b/modules/camera/3_4/V4L2CameraHAL.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright 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.
+ */
+
+// Modified from hardware/libhardware/modules/camera/CameraHAL.cpp
+
+#include "V4L2CameraHAL.h"
+
+#include <cstdlib>
+
+#include "Common.h"
+#include "V4L2Camera.h"
+
+/*
+ * This file serves as the entry point to the HAL. It is modified from the
+ * example default HAL available in hardware/libhardware/modules/camera.
+ * It contains the module structure and functions used by the framework
+ * to load and interface to this HAL, as well as the handles to the individual
+ * camera devices.
+ */
+
+namespace v4l2_camera_hal {
+
+// 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();
+  // TODO(29160300): Populate camera devices.
+}
+
+V4L2CameraHAL::~V4L2CameraHAL() {
+  HAL_LOG_ENTER();
+}
+
+int V4L2CameraHAL::getNumberOfCameras() {
+  HAL_LOGV("returns %d", mCameras.size());
+  return mCameras.size();
+}
+
+int V4L2CameraHAL::getCameraInfo(int id, camera_info_t* info) {
+  HAL_LOG_ENTER();
+  if (id < 0 || id >= mCameras.size()) {
+    return -EINVAL;
+  }
+  // TODO(b/29185945): Hotplugging: return -EINVAL if unplugged.
+  return mCameras[id]->getInfo(info);
+}
+
+int V4L2CameraHAL::setCallbacks(const camera_module_callbacks_t* callbacks) {
+  HAL_LOG_ENTER();
+  mCallbacks = callbacks;
+  return 0;
+}
+
+void V4L2CameraHAL::getVendorTagOps(vendor_tag_ops_t* ops) {
+  HAL_LOG_ENTER();
+  // No vendor ops for this HAL. From <hardware/camera_common.h>:
+  // "leave ops unchanged if no vendor tags are defined."
+}
+
+int V4L2CameraHAL::openLegacy(const hw_module_t* module, const char* id,
+                              uint32_t halVersion, hw_device_t** device) {
+  HAL_LOG_ENTER();
+  // Not supported.
+  return -ENOSYS;
+}
+
+int V4L2CameraHAL::setTorchMode(const char* camera_id, bool enabled) {
+  HAL_LOG_ENTER();
+  // TODO(b/29158098): HAL is required to respond appropriately if
+  // the desired camera actually does support flash.
+  return -ENOSYS;
+}
+
+int V4L2CameraHAL::open(const hw_module_t* module, const char* name,
+                        hw_device_t** device) {
+  HAL_LOG_ENTER();
+
+  if (module != &HAL_MODULE_INFO_SYM.common) {
+    HAL_LOGE("Invalid module %p expected %p", module,
+             &HAL_MODULE_INFO_SYM.common);
+    return -EINVAL;
+  }
+
+  int id = id_from_name(name);
+  if (id < 0) {
+    return id;
+  } else if (id < 0 || id >= mCameras.size()) {
+    return -EINVAL;
+  }
+  // TODO(b/29185945): Hotplugging: return -EINVAL if unplugged.
+  return mCameras[id]->open(module, device);
+}
+
+/*
+ * The framework calls the following wrappers, which in turn
+ * call the corresponding methods of the global HAL object.
+ */
+
+static int get_number_of_cameras() {
+  return gCameraHAL.getNumberOfCameras();
+}
+
+static int get_camera_info(int id, struct camera_info* info) {
+  return gCameraHAL.getCameraInfo(id, info);
+}
+
+static int set_callbacks(const camera_module_callbacks_t *callbacks) {
+  return gCameraHAL.setCallbacks(callbacks);
+}
+
+static void get_vendor_tag_ops(vendor_tag_ops_t* ops) {
+  return gCameraHAL.getVendorTagOps(ops);
+}
+
+static int open_legacy(const hw_module_t* module, const char* id,
+                       uint32_t halVersion, hw_device_t** device) {
+  return gCameraHAL.openLegacy(module, id, halVersion, device);
+}
+
+static int set_torch_mode(const char* camera_id, bool enabled) {
+  return gCameraHAL.setTorchMode(camera_id, enabled);
+}
+
+static int open_dev(const hw_module_t* module, const char* name,
+                    hw_device_t** device) {
+  return gCameraHAL.open(module, name, device);
+}
+
+}  // namespace v4l2_camera_hal
+
+static hw_module_methods_t v4l2_module_methods = {
+  .open = v4l2_camera_hal::open_dev
+};
+
+camera_module_t HAL_MODULE_INFO_SYM = {
+  .common = {
+    .tag =                 HARDWARE_MODULE_TAG,
+    .module_api_version =  CAMERA_MODULE_API_VERSION_2_4,
+    .hal_api_version =     HARDWARE_HAL_API_VERSION,
+    .id =                  CAMERA_HARDWARE_MODULE_ID,
+    .name =                "V4L2 Camera HAL v3",
+    .author =              "The Android Open Source Project",
+    .methods =             &v4l2_module_methods,
+    .dso =                 nullptr,
+    .reserved =            {0},
+  },
+  .get_number_of_cameras =  v4l2_camera_hal::get_number_of_cameras,
+  .get_camera_info =        v4l2_camera_hal::get_camera_info,
+  .set_callbacks =          v4l2_camera_hal::set_callbacks,
+  .get_vendor_tag_ops =     v4l2_camera_hal::get_vendor_tag_ops,
+  .open_legacy =            v4l2_camera_hal::open_legacy,
+  .set_torch_mode =         v4l2_camera_hal::set_torch_mode,
+  .init =                   nullptr,
+  .reserved =               {nullptr, nullptr, nullptr, nullptr, nullptr}
+};