Initial static info.

Fills in initial values for all required static info
fields for LIMITED devices. Currently fakes entries
that will eventually be queried from the device (open
bug https://b/29394024).

BUG: https://b/29214526, https://b/29221641
Change-Id: I6b4bfa172c882df22159da63378902cea7cc76fd
diff --git a/modules/camera/3_4/Camera.cpp b/modules/camera/3_4/Camera.cpp
index 6e9e12a..0014a39 100644
--- a/modules/camera/3_4/Camera.cpp
+++ b/modules/camera/3_4/Camera.cpp
@@ -60,7 +60,7 @@
     memset(&mTemplates, 0, sizeof(mTemplates));
     memset(&mDevice, 0, sizeof(mDevice));
     mDevice.common.tag    = HARDWARE_DEVICE_TAG;
-    mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0;
+    mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_4;
     mDevice.common.close  = close_device;
     mDevice.ops           = const_cast<camera3_device_ops_t*>(&sOps);
     mDevice.priv          = this;
@@ -109,9 +109,10 @@
     info->device_version = mDevice.common.version;
     initDeviceInfo(info);
     if (mStaticInfo == NULL) {
-        mStaticInfo = initStaticInfo();
+      if (initStaticInfo(&mStaticInfo)) {
+        return -ENODEV;
+      }
     }
-
     info->static_camera_characteristics = mStaticInfo;
     return 0;
 }
@@ -319,7 +320,7 @@
 
 bool Camera::isValidTemplateType(int type)
 {
-    return type < 1 || type >= CAMERA3_TEMPLATE_COUNT;
+    return type > 0 && type < CAMERA3_TEMPLATE_COUNT;
 }
 
 const camera_metadata_t* Camera::constructDefaultRequestSettings(int type)
@@ -514,7 +515,7 @@
     return "Invalid template type!";
 }
 
-int Camera::setTemplate(int type, camera_metadata_t *settings)
+int Camera::setTemplate(int type, const camera_metadata_t *settings)
 {
     android::Mutex::Autolock al(mDeviceLock);
 
@@ -558,6 +559,7 @@
     return camdev_to_camera(dev)->configureStreams(stream_list);
 }
 
+  // TODO: remove
 static int register_stream_buffers(const camera3_device_t *dev,
         const camera3_stream_buffer_set_t *buffer_set)
 {
@@ -592,7 +594,7 @@
 const camera3_device_ops_t Camera::sOps = {
     .initialize = default_camera_hal::initialize,
     .configure_streams = default_camera_hal::configure_streams,
-    .register_stream_buffers = default_camera_hal::register_stream_buffers,
+    .register_stream_buffers = nullptr,
     .construct_default_request_settings
         = default_camera_hal::construct_default_request_settings,
     .process_capture_request = default_camera_hal::process_capture_request,
diff --git a/modules/camera/3_4/Camera.h b/modules/camera/3_4/Camera.h
index 3ecd0a8..a61cee2 100644
--- a/modules/camera/3_4/Camera.h
+++ b/modules/camera/3_4/Camera.h
@@ -59,7 +59,7 @@
         // 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;
+        virtual int initStaticInfo(camera_metadata_t **out) = 0;
         // Initialize device info: facing, orientation, resource cost,
         // and conflicting devices (/conflicting devices length)
         virtual void initDeviceInfo(struct camera_info *info) = 0;
@@ -68,7 +68,7 @@
         // Separate initialization method for individual devices when opened
         virtual int initDevice() = 0;
         // Accessor used by initDevice() to set the templates' metadata
-        int setTemplate(int type, camera_metadata_t *static_info);
+        int setTemplate(int type, const camera_metadata_t *static_info);
         // Prettyprint template names
         const char* templateToString(int type);
 
diff --git a/modules/camera/3_4/V4L2Camera.cpp b/modules/camera/3_4/V4L2Camera.cpp
index 5e5c0c4..80e635a 100644
--- a/modules/camera/3_4/V4L2Camera.cpp
+++ b/modules/camera/3_4/V4L2Camera.cpp
@@ -26,6 +26,8 @@
 
 #include "Common.h"
 
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
 namespace v4l2_camera_hal {
 
 V4L2Camera::V4L2Camera(int id, std::string path)
@@ -58,23 +60,490 @@
   //   (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)
+
+  // TODO(b/29158098): Inform service of any flashes that are no longer available
+  //   because this camera is in use.
   return 0;
 }
 
 void V4L2Camera::disconnect() {
   HAL_LOG_ENTER();
+  // TODO(b/29158098): Inform service of any flashes that are available again
+  //   because this camera is no longer in use.
+
   mDeviceFd.reset();
 }
 
-camera_metadata_t* V4L2Camera::initStaticInfo() {
+int V4L2Camera::initStaticInfo(camera_metadata_t** out) {
   HAL_LOG_ENTER();
 
-  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);
+  android::CameraMetadata info;
 
-  return metadata.release();
+  std::vector<int32_t> avail_characteristics_keys;
+  android::status_t res;
+
+#define ADD_STATIC_ENTRY(name, varptr, count)   \
+  avail_characteristics_keys.push_back(name); \
+  res = info.update(name, varptr, count);     \
+  if (res != android::OK) return res
+
+  // Static metadata characteristics from /system/media/camera/docs/docs.html.
+
+  /* android.color. */
+
+  // No easy way to turn chromatic aberration correction OFF in v4l2,
+  // though this may be supportable via a collection of other user controls.
+  uint8_t avail_aberration_modes[] = {
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY};
+  ADD_STATIC_ENTRY(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+                   avail_aberration_modes, ARRAY_SIZE(avail_aberration_modes));
+
+  /* android.control. */
+
+  /*   3As */
+
+  // TODO(b/29394024): query V4L2_CID_POWER_LINE_FREQUENCY
+  uint8_t avail_ae_antibanding_modes[] = {
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+                   avail_ae_antibanding_modes,
+                   ARRAY_SIZE(avail_ae_antibanding_modes));
+
+  // TODO(b/29394024): query V4L2_CID_EXPOSURE_AUTO for ae modes.
+  uint8_t avail_ae_modes[] = {
+    ANDROID_CONTROL_AE_MODE_ON};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_AVAILABLE_MODES,
+                   avail_ae_modes, ARRAY_SIZE(avail_ae_modes));
+
+  // TODO(b/29394034): query available YUV_420_888 frame rates.
+  //   This should be {mi, ma, ma, ma} where mi is min(15, min frame rate),
+  //   and ma is max frame rate (for YUV_420_888).
+  int32_t avail_fps_ranges[] = {
+    15, 30,
+    30, 30};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+                   avail_fps_ranges, ARRAY_SIZE(avail_fps_ranges));
+
+  // TODO(b/29394024): query V4L2_CID_EXPOSURE_BIAS.
+  int32_t ae_comp_range[] = {0, 0};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+                   ae_comp_range, ARRAY_SIZE(ae_comp_range));
+
+  // TODO(b/29394024): set based on V4L2_CID_EXPOSURE_BIAS step size.
+  camera_metadata_rational ae_comp_step = {1, 1};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_COMPENSATION_STEP,
+                   &ae_comp_step, 1);
+
+  // TODO(b/29394024): query V4L2_CID_FOCUS_AUTO for
+  //   CONTINUOUS_VIDEO/CONTINUOUS_PICTURE. V4L2_CID_AUTO_FOCUS_START
+  //   supports what Android thinks of as auto focus (single auto focus).
+  //   V4L2_CID_AUTO_FOCUS_RANGE allows MACRO.
+  uint8_t avail_af_modes[] = {
+    ANDROID_CONTROL_AF_MODE_OFF};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AF_AVAILABLE_MODES,
+                   avail_af_modes, ARRAY_SIZE(avail_af_modes));
+
+  // TODO(b/29394024): query V4L2_CID_AUTO_WHITE_BALANCE, or
+  //   V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE if available.
+  // If manual is supported, must look at android.colorCorrection
+  //   transform and gains for the manual control. Not sure if this
+  //   is supported by V4L2 or not, or if this is even a HAL job.
+  uint8_t avail_awb_modes[] = {
+    ANDROID_CONTROL_AWB_MODE_AUTO};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+                   avail_awb_modes, ARRAY_SIZE(avail_awb_modes));
+
+  // Couldn't find any V4L2 support for regions, though maybe it's out there.
+  int32_t max_regions[] = {/*AE*/ 0,/*AWB*/ 0,/*AF*/ 0};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_MAX_REGIONS,
+                   max_regions, ARRAY_SIZE(max_regions));
+
+  // TODO(b/29394024): query V4L2_CID_3A_LOCK.
+  uint8_t ae_lock_avail = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+                   &ae_lock_avail, 1);
+  uint8_t awb_lock_avail = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+                   &awb_lock_avail, 1);
+
+  /*   Scene modes. */
+
+  // TODO(b/29394024): query V4L2_CID_SCENE_MODE.
+  uint8_t avail_scene_modes[] = {
+    ANDROID_CONTROL_SCENE_MODE_DISABLED};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+                   avail_scene_modes, ARRAY_SIZE(avail_scene_modes));
+
+  // A 3-tuple of AE, AWB, AF overrides for each scene mode.
+  // Ignored for DISABLED, FACE_PRIORITY and FACE_PRIORITY_LOW_LIGHT.
+  uint8_t scene_mode_overrides[] = {
+    /*SCENE_MODE_DISABLED*/ /*AE*/0, /*AW*/0, /*AF*/0};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
+                   scene_mode_overrides, ARRAY_SIZE(scene_mode_overrides));
+
+  /*   Top level 3A/Scenes switch. */
+
+  // TODO(b/29394024): Add USE_SCENE_MODE if scene modes are enabled.
+  uint8_t avail_modes[] = {
+    ANDROID_CONTROL_MODE_AUTO};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_MODES,
+                   avail_modes, ARRAY_SIZE(avail_modes));
+
+  /*   Other android.control configuration. */
+
+  // TODO(b/29394024): query V4L2_CID_IMAGE_STABILIZATION.
+  uint8_t avail_stabilization[] = {
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+                   avail_stabilization, ARRAY_SIZE(avail_stabilization));
+
+  // TODO(b/29394024): query V4L2_CID_COLORFX.
+  uint8_t avail_effects[] = {
+    ANDROID_CONTROL_EFFECT_MODE_OFF};
+  ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_EFFECTS,
+                   avail_effects, ARRAY_SIZE(avail_effects));
+
+  // AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS only necessary
+  // for devices supporting CONSTRAINED_HIGH_SPEED_VIDEO,
+  // which this HAL doesn't support.
+
+  // POST_RAW_SENSITIVITY_BOOST_RANGE only necessary
+  // for devices supporting RAW format outputs.
+
+  /* android.edge. */
+
+  // Not sure if V4L2 does or doesn't do this, but HAL documentation says
+  // all devices must support FAST, and FAST can be equivalent to OFF, so
+  // either way it's fine to list.
+  uint8_t avail_edge_modes[] = {
+    ANDROID_EDGE_MODE_FAST};
+  ADD_STATIC_ENTRY(ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+                   avail_edge_modes, ARRAY_SIZE(avail_edge_modes));
+
+  /* android.flash. */
+
+  // TODO(b/29394024): query V4L2_CID_FLASH_LED_MODE.
+  uint8_t flash_avail = 0;
+  ADD_STATIC_ENTRY(ANDROID_FLASH_INFO_AVAILABLE,
+                   &flash_avail, 1);
+
+  // info.chargeDuration, color.Temperature, maxEnergy marked FUTURE.
+
+  /* android.hotPixel. */
+
+  // No known V4L2 hot pixel correction. But it might be happening,
+  // so we report FAST/HIGH_QUALITY.
+  uint8_t avail_hot_pixel_modes[] = {
+    ANDROID_HOT_PIXEL_MODE_FAST,
+    ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY};
+  ADD_STATIC_ENTRY(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
+                   avail_hot_pixel_modes, ARRAY_SIZE(avail_hot_pixel_modes));
+
+  /* android.jpeg. */
+
+  // For now, no thumbnails available (only [0,0], the "no thumbnail" size).
+  // TODO(b/29580107): Could end up with a mismatch between request & result,
+  //   since V4L2 doesn't actually allow for thumbnail size control.
+  int32_t thumbnail_sizes[] = {
+    0, 0};
+  ADD_STATIC_ENTRY(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+                   thumbnail_sizes, ARRAY_SIZE(thumbnail_sizes));
+
+  // V4L2 doesn't support querying this, so we generously assume up to 3 MB.
+  int32_t max_jpeg_size = 3000000;
+  ADD_STATIC_ENTRY(ANDROID_JPEG_MAX_SIZE,
+                   &max_jpeg_size, 1);
+
+  /* android.lens. */
+
+  /*   Misc. lens control. */
+
+  // No way to actually get the f-value in V4L2, but it's a required key,
+  // so we just fake it. Raspberry Pi camera v2 is f/2.0.
+  float avail_apertures[] = {2.0};
+  ADD_STATIC_ENTRY(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
+                   avail_apertures, ARRAY_SIZE(avail_apertures));
+
+  // No known V4L2 neutral density filter control.
+  float avail_filter_densities[] = {0.0};
+  ADD_STATIC_ENTRY(ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
+                   avail_filter_densities, ARRAY_SIZE(avail_filter_densities));
+
+  // TODO(b/29394024): query V4L2_CID_IMAGE_STABILIZATION.
+  uint8_t avail_optical_stabilization[] = {
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF};
+  ADD_STATIC_ENTRY(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+                   avail_optical_stabilization,
+                   ARRAY_SIZE(avail_optical_stabilization));
+
+  // No known V4L2 shading map info.
+  int32_t shading_map_size[] = {1, 1};
+  ADD_STATIC_ENTRY(ANDROID_LENS_INFO_SHADING_MAP_SIZE,
+                   shading_map_size, ARRAY_SIZE(shading_map_size));
+
+  // All V4L2 devices are considered to be external facing.
+  uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
+  ADD_STATIC_ENTRY(ANDROID_LENS_FACING, &facing, 1);
+
+  /*   Zoom/Focus. */
+
+  // No way to actually get the focal length in V4L2, but it's a required key,
+  // so we just fake it. Raspberry Pi camera v2 is 3.04mm.
+  // Note: unlike f values, this key is actually used in calculations
+  //   (field of view), so other cameras may see inaccurate results.
+  float focal_length = 3.04;
+  ADD_STATIC_ENTRY(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+                   &focal_length, 1);
+
+  // V4L2 focal units do not correspond to a particular physical unit.
+  uint8_t focus_calibration =
+      ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
+  ADD_STATIC_ENTRY(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+                   &focus_calibration, 1);
+
+  // info.hyperfocalDistance not required for UNCALIBRATED.
+
+  // TODO(b/29394024): query V4L2_CID_ZOOM_ABSOLUTE for focus range.
+  // 0 is fixed focus.
+  float min_focus_distance = 0.0;
+  ADD_STATIC_ENTRY(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
+                   &min_focus_distance, 1);
+
+  /*   Depth. */
+
+  // DEPTH capability not supported by this HAL. Not implemented:
+  //   poseRotation
+  //   poseTranslation
+  //   intrinsicCalibration
+  //   radialDistortion
+
+  /* anroid.noise. */
+
+  // Unable to control noise reduction in V4L2 devices,
+  // but FAST is allowed to be the same as OFF.
+  uint8_t avail_noise_reduction_modes[] = {
+    ANDROID_NOISE_REDUCTION_MODE_FAST};
+  ADD_STATIC_ENTRY(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+                   avail_noise_reduction_modes,
+                   ARRAY_SIZE(avail_noise_reduction_modes));
+
+  /* android.request. */
+
+  // Resources may be an issue, so just using minimum allowable
+  // for LIMITED devices.
+  int32_t max_num_output_streams[] = {
+    /*Raw*/0, /*YUV*/2, /*JPEG*/1};
+  ADD_STATIC_ENTRY(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+                   max_num_output_streams, ARRAY_SIZE(max_num_output_streams));
+
+  // Reprocessing not supported, so no maxNumInputStreams.
+
+  // No way to know for V4L2, so fake with max allowable latency.
+  // Doesn't mean much without per-frame controls.
+  uint8_t pipeline_max_depth = 4;
+  ADD_STATIC_ENTRY(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+                   &pipeline_max_depth, 1);
+
+  // Partial results not supported; partialResultCount defaults to 1.
+
+  // Available capabilities & keys queried at very end of this method.
+
+  /* android.scaler. */
+
+  /*   Cropping. */
+
+  // TODO(b/29394024): query VIDIOC_CROPCAP to get cropping ranges,
+  //   and VIDIOC_G_CROP to determine if cropping is supported.
+  //   If the ioctl isn't available (or cropping has non-square pixelaspect),
+  //   assume no cropping/scaling.
+  //   May need to try setting some crops to determine what the driver actually
+  //   supports (including testing center vs freeform).
+  float max_zoom = 1;
+  ADD_STATIC_ENTRY(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+                   &max_zoom, 1);
+
+  // V4L2 VIDIOC_CROPCAP doesn't give a way to query this;
+  //   it's driver dependent. For now, assume freeform, and
+  //   some cameras may just behave badly.
+  // TODO(b/29579652): Figure out a way to determine this.
+  uint8_t crop_type = ANDROID_SCALER_CROPPING_TYPE_FREEFORM;
+  ADD_STATIC_ENTRY(ANDROID_SCALER_CROPPING_TYPE, &crop_type, 1);
+
+  /*   Streams. */
+
+  // availableInputOutputFormatsMap only required for reprocessing capability.
+
+  // TODO(b/29394024): query VIDIOC_ENUM_FMT to get pixel formats, pull out
+  //   YUV_420_888 and JPEG, query VIDIOC_ENUM_FRAMESIZES on those.
+  // TODO(b/29581206): Need behavior if YUV_420_888 and JPEG aren't available.
+  // For now, just 640x480 JPEG.
+  int32_t avail_stream_configs[] = {
+    HAL_PIXEL_FORMAT_BLOB, 640, 480,
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT};
+  ADD_STATIC_ENTRY(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+                   avail_stream_configs, ARRAY_SIZE(avail_stream_configs));
+
+  // Per format and size, minimum frame duration (max frame rate).
+  // For now, just 30 fps = 1/30 spf ~= 33333333 ns.
+  //   For whatever reason the goldfish/qcom cameras report this as
+  //   33331760, so copying that.
+  // TODO(b/29394024): query the available format frame rates.
+  int64_t avail_min_frame_durations[] = {
+    HAL_PIXEL_FORMAT_BLOB, 640, 480, 33331760};
+  ADD_STATIC_ENTRY(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+                   avail_min_frame_durations,
+                   ARRAY_SIZE(avail_min_frame_durations));
+
+  // Per format and size, usually 0 for non-jpeg, non-zero for JPEG.
+  // Randomly choosing absurdly long 1 sec for JPEG. Unsure what this breaks.
+  int64_t avail_stall_durations[] = {
+    HAL_PIXEL_FORMAT_BLOB, 640, 480, 1000000000};
+  ADD_STATIC_ENTRY(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
+                   avail_stall_durations, ARRAY_SIZE(avail_stall_durations));
+
+  /* android.sensor. */
+
+  /*   Sizes. */
+
+  // Spoof as 640 x 480 for now.
+  // TODO(b/29394024): query VIDIOC_CROPCAP to get pixel rectangle.
+  int32_t array_rect[] = {
+    /*xmin*/0, /*ymin*/0, /*width*/640, /*height*/480};
+  ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+                   array_rect, ARRAY_SIZE(array_rect));
+  // No V4L2 way to differentiate active vs. inactive parts of the rectangle.
+  ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+                   array_rect, ARRAY_SIZE(array_rect));
+
+  // No way to get actual physical size from V4L2. Field of view/pixel pitch
+  // calculations will be off. Using Raspberry Pi camera v2 measurements
+  // (3.674 x 2.760 mm).
+  float physical_size[] = {3.674, 2.760};
+  ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+                   physical_size, ARRAY_SIZE(physical_size));
+
+  /*   Misc sensor information. */
+
+  // For now, using the emulator value of .3 sec.
+  // TODO(b/29394024): query for min frame rate.
+  int64_t max_frame_duration = 300000000;
+  ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+                   &max_frame_duration, 1);
+
+  // HAL uses BOOTTIME timestamps.
+  // TODO(b/29457051): make sure timestamps are consistent throughout the HAL.
+  uint8_t timestamp_source = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
+  ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+                   &timestamp_source, 1);
+
+  // As in initDeviceInfo, no way to actually get orientation.
+  int32_t orientation = 0;
+  ADD_STATIC_ENTRY(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
+
+  // availableTestPatternModes just defaults to OFF, which is fine.
+
+  // info.exposureTimeRange, info.sensitivityRange:
+  //   exposure/sensitivity manual control not supported.
+  //   Could query V4L2_CID_ISO_SENSITIVITY to support sensitivity if desired.
+
+  // info.whiteLevel, info.lensShadingApplied,
+  //   info.preCorrectionActiveArraySize, referenceIlluminant1/2,
+  //   calibrationTransform1/2, colorTransform1/2, forwardMatrix1/2,
+  //   blackLevelPattern, profileHueSatMapDimensions
+  //   all only necessary for RAW.
+
+  // baseGainFactor marked FUTURE.
+
+  // maxAnalogSensitivity optional for LIMITED device.
+
+  // opticalBlackRegions: No known way to get in V4L2, but not necessary.
+
+  // opaqueRawSize not necessary since RAW_OPAQUE format not supported.
+
+  /* android.statistics */
+
+  // Face detection not supported.
+  uint8_t avail_face_detect_modes[] = {
+    ANDROID_STATISTICS_FACE_DETECT_MODE_OFF};
+  ADD_STATIC_ENTRY(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+                   avail_face_detect_modes,
+                   ARRAY_SIZE(avail_face_detect_modes));
+
+  int32_t max_face_count = 0;
+  ADD_STATIC_ENTRY(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+                   &max_face_count, 1);
+
+  // info.histogramBucketCount, info.maxHistogramCount,
+  //   info.maxSharpnessMapValue, info.sharpnessMapSizemarked FUTURE.
+
+  // ON only needs to be supported for RAW capable devices.
+  uint8_t avail_hot_pixel_map_modes[] = {
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF};
+  ADD_STATIC_ENTRY(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
+                   avail_hot_pixel_map_modes,
+                   ARRAY_SIZE(avail_hot_pixel_map_modes));
+
+  // ON only needs to be supported for RAW capable devices.
+  uint8_t avail_lens_shading_map_modes[] = {
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF};
+  ADD_STATIC_ENTRY(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+                   avail_lens_shading_map_modes,
+                   ARRAY_SIZE(avail_lens_shading_map_modes));
+
+  /* android.tonemap. */
+
+  // tonemapping only required for MANUAL_POST_PROCESSING capability.
+
+  /* android.led. */
+
+  // availableLeds: for now, none available, so no need to set.
+  // TODO(b/29394024): query V4L2_CID_FLASH_INDICATOR_INTENSITY?
+  //   if it's there, assume indicator exists?
+
+  /* android.sync. */
+
+  // "LIMITED devices are strongly encouraged to use a non-negative value.
+  //   If UNKNOWN is used here then app developers do not have a way to know
+  //   when sensor settings have been applied." - Unfortunately, V4L2 doesn't
+  //   really help here either. Could even be that adjusting settings mid-stream
+  //   blocks in V4L2, and should be avoided.
+  int32_t max_latency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
+  ADD_STATIC_ENTRY(ANDROID_SYNC_MAX_LATENCY,
+                   &max_latency, 1);
+
+  /* android.reprocess. */
+
+  // REPROCESSING not supported by this HAL.
+
+  /* android.depth. */
+
+  // DEPTH not supported by this HAL.
+
+  /* Capabilities and android.info. */
+
+  uint8_t hw_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+  ADD_STATIC_ENTRY(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+                   &hw_level, 1);
+
+  uint8_t capabilities[] = {
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
+  ADD_STATIC_ENTRY(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+                   capabilities, ARRAY_SIZE(capabilities));
+
+  // TODO(b/29221795): available request keys
+  //   (fill in when writing default requests).
+
+  // TODO(b/29335262): available result keys
+  //   (fill in when writing actual result capture).
+
+  // Last thing, once all the available characteristics have been added.
+  info.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+              &avail_characteristics_keys[0],
+              avail_characteristics_keys.size());
+
+  *out = info.release();
+  return 0;
 }
 
 void V4L2Camera::initDeviceInfo(camera_info_t* info) {
diff --git a/modules/camera/3_4/V4L2Camera.h b/modules/camera/3_4/V4L2Camera.h
index 4cc0103..ff7275a 100644
--- a/modules/camera/3_4/V4L2Camera.h
+++ b/modules/camera/3_4/V4L2Camera.h
@@ -40,18 +40,18 @@
 private:
   // default_camera_hal::Camera virtual methods.
   // Connect to the device: open dev nodes, etc.
-  int connect();
+  int connect() override;
   // Disconnect from the device: close dev nodes, etc.
-  void disconnect();
+  void disconnect() override;
   // Initialize static camera characteristics for individual device.
-  camera_metadata_t *initStaticInfo();
+  int initStaticInfo(camera_metadata_t** out) override;
   // Initialize device info: facing, orientation, resource cost,
   // and conflicting devices (/conflicting devices length).
-  void initDeviceInfo(camera_info_t* info);
+  void initDeviceInfo(camera_info_t* info) override;
   // Initialize whole device (templates/etc) when opened.
-  int initDevice();
+  int initDevice() override;
   // Verify settings are valid for a capture with this device.
-  bool isValidCaptureSettings(const camera_metadata_t* settings);
+  bool isValidCaptureSettings(const camera_metadata_t* settings) override;
 
   // The camera device path. For example, /dev/video0.
   const std::string mDevicePath;