Switch to composition over inheritance.

Switches v4l2_metadata over to the updated controls/properties
using inheritance over composition. Slight regression
in that the V4L2-based control factory method was removed,
will be replaced (and improved) in a CL soon.

BUG: 30140438
TEST: unit tests pass
Change-Id: I636fef67cd3ceeb3ebf9853d04b068988c4c4944
diff --git a/modules/camera/3_4/metadata/control.h b/modules/camera/3_4/metadata/control.h
index eff8c2f..199ecd0 100644
--- a/modules/camera/3_4/metadata/control.h
+++ b/modules/camera/3_4/metadata/control.h
@@ -22,18 +22,29 @@
 #include <system/camera_metadata.h>
 
 #include "../common.h"
+#include "menu_control_options.h"
 #include "metadata_common.h"
-#include "tagged_partial_metadata.h"
+#include "no_effect_control_delegate.h"
+#include "partial_metadata_interface.h"
+#include "tagged_control_delegate.h"
+#include "tagged_control_options.h"
 
 namespace v4l2_camera_hal {
 
 // A Control is a PartialMetadata with values that can be gotten/set.
 template <typename T>
-class Control : public TaggedPartialMetadata {
+class Control : public PartialMetadataInterface {
  public:
-  Control(int32_t control_tag, std::vector<int32_t> static_tags = {});
+  // Options are optional (i.e. nullable), delegate is not.
+  Control(std::unique_ptr<TaggedControlDelegate<T>> delegate,
+          std::unique_ptr<TaggedControlOptions<T>> options = nullptr);
 
-  // Child classes still need to implement PopulateStaticFields.
+  virtual std::vector<int32_t> StaticTags() const override;
+  virtual std::vector<int32_t> ControlTags() const override;
+  virtual std::vector<int32_t> DynamicTags() const override;
+
+  virtual int PopulateStaticFields(
+      android::CameraMetadata* metadata) const override;
   virtual int PopulateDynamicFields(
       android::CameraMetadata* metadata) const override;
   virtual bool SupportsRequestValues(
@@ -41,20 +52,15 @@
   virtual int SetRequestValues(
       const android::CameraMetadata& metadata) override;
 
- protected:
-  // Simpler access to tag.
-  inline int32_t ControlTag() const { return ControlTags()[0]; }
+  // Factory methods for some common combinations of delegates & options.
+  // NoEffectMenuControl: Some menu options, but they have no effect.
+  // The default value will be the first element of |options|.
+  static std::unique_ptr<Control<T>> NoEffectMenuControl(
+      int32_t delegate_tag, int32_t options_tag, const std::vector<T>& options);
 
-  // Get/Set the control value. Return non-0 on failure.
-  // Controls are allowed to be unreliable, so SetValue is best-effort;
-  // GetValue immediately after may not match (SetValue may, for example,
-  // automatically replace invalid values with valid ones,
-  // or have a delay before setting the requested value).
-  // GetValue should always indicate the actual current value of the control.
-  virtual int GetValue(T* value) const = 0;
-  virtual int SetValue(const T& value) = 0;
-  // Helper to check if val is supported by this control.
-  virtual bool IsSupported(const T& val) const = 0;
+ protected:
+  std::unique_ptr<TaggedControlDelegate<T>> delegate_;
+  std::unique_ptr<TaggedControlOptions<T>> options_;
 
   DISALLOW_COPY_AND_ASSIGN(Control);
 };
@@ -62,24 +68,55 @@
 // -----------------------------------------------------------------------------
 
 template <typename T>
-Control<T>::Control(int32_t control_tag, std::vector<int32_t> static_tags)
-    // Controls use the same tag for setting the control
-    // and getting the dynamic value.
-    : TaggedPartialMetadata(static_tags, {control_tag}, {control_tag}) {
+Control<T>::Control(std::unique_ptr<TaggedControlDelegate<T>> delegate,
+                    std::unique_ptr<TaggedControlOptions<T>> options)
+    : delegate_(std::move(delegate)), options_(std::move(options)) {
   HAL_LOG_ENTER();
 }
 
 template <typename T>
+std::vector<int32_t> Control<T>::StaticTags() const {
+  std::vector<int32_t> result;
+  if (options_) {
+    result.push_back(options_->tag());
+  }
+  return result;
+}
+
+template <typename T>
+std::vector<int32_t> Control<T>::ControlTags() const {
+  return {delegate_->tag()};
+}
+
+template <typename T>
+std::vector<int32_t> Control<T>::DynamicTags() const {
+  return {delegate_->tag()};
+}
+
+template <typename T>
+int Control<T>::PopulateStaticFields(android::CameraMetadata* metadata) const {
+  HAL_LOG_ENTER();
+
+  if (!options_) {
+    HAL_LOGV("No options for control, nothing to populate.");
+    return 0;
+  }
+
+  return UpdateMetadata(
+      metadata, options_->tag(), options_->MetadataRepresentation());
+}
+
+template <typename T>
 int Control<T>::PopulateDynamicFields(android::CameraMetadata* metadata) const {
   HAL_LOG_ENTER();
 
   // Populate the current setting.
   T value;
-  int res = GetValue(&value);
+  int res = delegate_->GetValue(&value);
   if (res) {
     return res;
   }
-  return UpdateMetadata(metadata, ControlTag(), value);
+  return UpdateMetadata(metadata, delegate_->tag(), value);
 }
 
 template <typename T>
@@ -91,18 +128,25 @@
     return true;
   }
 
-  // Check that the requested setting is in the supported options.
+  // Get the requested setting for this control.
   T requested;
-  int res = SingleTagValue(metadata, ControlTag(), &requested);
+  int res = SingleTagValue(metadata, delegate_->tag(), &requested);
   if (res == -ENOENT) {
     // Nothing requested of this control, that's fine.
     return true;
   } else if (res) {
     HAL_LOGE("Failure while searching for request value for tag %d",
-             ControlTag());
+             delegate_->tag());
     return false;
   }
-  return IsSupported(requested);
+
+  // Check that the requested setting is in the supported options.
+  if (!options_) {
+    HAL_LOGV("No options for control %d; request implicitly supported.",
+             delegate_->tag());
+    return true;
+  }
+  return options_->IsSupported(requested);
 }
 
 template <typename T>
@@ -115,17 +159,41 @@
 
   // Get the requested value.
   T requested;
-  int res = SingleTagValue(metadata, ControlTag(), &requested);
+  int res = SingleTagValue(metadata, delegate_->tag(), &requested);
   if (res == -ENOENT) {
     // Nothing requested of this control, nothing to do.
     return 0;
   } else if (res) {
     HAL_LOGE("Failure while searching for request value for tag %d",
-             ControlTag());
+             delegate_->tag());
     return res;
   }
 
-  return SetValue(requested);
+  // Check that the value is supported.
+  if (options_ && !options_->IsSupported(requested)) {
+    HAL_LOGE("Unsupported value requested for control %d.", delegate_->tag());
+    return -EINVAL;
+  }
+
+  return delegate_->SetValue(requested);
+}
+
+template <typename T>
+std::unique_ptr<Control<T>> Control<T>::NoEffectMenuControl(
+    int32_t delegate_tag, int32_t options_tag, const std::vector<T>& options) {
+  HAL_LOG_ENTER();
+
+  if (options.empty()) {
+    HAL_LOGE("At least one option must be provided.");
+    return nullptr;
+  }
+
+  return std::make_unique<Control<T>>(
+      std::make_unique<TaggedControlDelegate<T>>(
+          delegate_tag,
+          std::make_unique<NoEffectControlDelegate<T>>(options[0])),
+      std::make_unique<TaggedControlOptions<T>>(
+          options_tag, std::make_unique<MenuControlOptions<T>>(options)));
 }
 
 }  // namespace v4l2_camera_hal