Update optics

* Specify optics via system properties

Bug: 36039976
Test: Ran on device

Change-Id: I7a38e5a9eb3b8a861f1997d5011ec109f5e79cca
diff --git a/libs/vr/libeds/device_metrics.cpp b/libs/vr/libeds/device_metrics.cpp
new file mode 100644
index 0000000..50c3e54
--- /dev/null
+++ b/libs/vr/libeds/device_metrics.cpp
@@ -0,0 +1,182 @@
+#include <private/dvr/device_metrics.h>
+
+#include <cutils/properties.h>
+#include <private/dvr/head_mount_metrics.h>
+#include <private/dvr/identity_distortion.h>
+#include <private/dvr/lookup_radial_distortion.h>
+#include <private/dvr/polynomial_radial_distortion.h>
+#include <private/dvr/types.h>
+#include "include/private/dvr/display_metrics.h"
+
+namespace {
+
+static constexpr char kRGBPolynomialOffset[] = "persist.dvr.rgb_poly_offset";
+static constexpr char kRPolynomial[] = "persist.dvr.r_poly";
+static constexpr char kGPolynomial[] = "persist.dvr.g_poly";
+static constexpr char kBPolynomial[] = "persist.dvr.b_poly";
+static constexpr char kLensDistance[] = "persist.dvr.lens_distance";
+static constexpr char kDisplayGap[] = "persist.dvr.display_gap";
+static constexpr char kVEyeToDisplay[] = "persist.dvr.v_eye_to_display";
+static constexpr char kFovIOBT[] = "persist.dvr.fov_iobt";
+static constexpr char kScreenSize[] = "persist.dvr.screen_size";
+
+bool StringToFloat(const char* str, float* result) {
+  char* endptr = nullptr;
+  *result = std::strtof(str, &endptr);
+  return !(str == endptr || !endptr);
+}
+
+std::vector<std::string> SplitString(const std::string& string_to_split,
+                                     char deliminator) {
+  std::vector<std::string> result;
+  std::string sub_string;
+  std::stringstream ss(string_to_split);
+  while (std::getline(ss, sub_string, deliminator))
+    result.push_back(sub_string);
+  return result;
+}
+
+std::vector<float> GetProperty(const char* name,
+                               const std::vector<float>& default_values) {
+  char prop[PROPERTY_VALUE_MAX + 1] = {};
+  property_get(name, prop, "");
+  std::vector<std::string> values = SplitString(prop, ',');
+  std::vector<float> results;
+  for (const auto& value : values) {
+    float result = 0.0f;
+    if (StringToFloat(value.c_str(), &result)) {
+      results.push_back(static_cast<float>(result));
+    }
+  }
+  if (results.empty()) {
+    return default_values;
+  }
+  return results;
+}
+
+float GetProperty(const char* name, float default_value) {
+  char prop[PROPERTY_VALUE_MAX + 1] = {};
+  property_get(name, prop, "");
+  float result = 0.0f;
+  if (StringToFloat(prop, &result)) {
+    return static_cast<float>(result);
+  }
+  return default_value;
+}
+
+float GetInterLensDistance() { return GetProperty(kLensDistance, 0.064f); }
+
+float GetDisplayGap() { return GetProperty(kDisplayGap, 0.0f); }
+
+float GetVEyeToDisplay() { return GetProperty(kVEyeToDisplay, 0.035f); }
+
+android::dvr::vec2 GetDisplaySize() {
+  static const std::vector<float> default_size = {0.0742177f, 0.131943f};
+  std::vector<float> sizes = GetProperty(kScreenSize, default_size);
+  if (sizes.size() != 0)
+    sizes = default_size;
+  return android::dvr::vec2(sizes[0], sizes[1]);
+}
+
+std::vector<float> GetMaxFOVs() {
+  static const std::vector<float> defaults = {43.7f, 47.8f, 54.2f, 54.2f};
+  std::vector<float> fovs = GetProperty(kFovIOBT, defaults);
+  if (fovs.size() != 4)
+    fovs = defaults;
+  for (auto& value : fovs) {
+    value = value * M_PI / 180.0f;
+  }
+  return fovs;
+}
+
+static const android::dvr::HeadMountMetrics::VerticalAlignment
+    kDefaultVerticalAlignment = android::dvr::HeadMountMetrics::kCenter;
+
+// Default border size in meters.
+static const float kScreenBorderSize = 0.004f;
+
+// Refresh rate.
+static const float kScreenRefreshRate = 60.0f;
+
+// Default display orientation is portrait.
+static const android::dvr::DisplayOrientation kDisplayOrientation =
+    android::dvr::DisplayOrientation::kPortrait;
+
+}  // anonymous namespace
+
+namespace android {
+namespace dvr {
+
+HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov,
+                                        const FieldOfView& r_fov) {
+  static const std::vector<float> default_r = {
+      -4.08519004f,  34.70282075f, -67.37781249f, 56.97304235f,
+      -23.35768685f, 4.7199597f,   0.63198082f};
+  static const std::vector<float> default_g = {
+      4.43078318f, 3.47806617f, -20.58017398f, 20.85880414f,
+      -8.4046504f, 1.61284685f, 0.8881761f};
+  static const std::vector<float> default_b = {
+      12.04141265f, -21.98112491f, 14.06758389f, -3.15245629f,
+      0.36549102f,  0.05252705f,   0.99844279f};
+  static const std::vector<float> default_offsets = {
+      0.20971645238f, 0.15189450000f, 1.00096958278f};
+
+  std::vector<float> poly_offsets =
+      GetProperty(kRGBPolynomialOffset, default_offsets);
+  std::vector<float> poly_r = GetProperty(kRPolynomial, default_r);
+  std::vector<float> poly_g = GetProperty(kGPolynomial, default_g);
+  std::vector<float> poly_b = GetProperty(kBPolynomial, default_b);
+  if (poly_offsets.size() != 3)
+    poly_offsets = default_offsets;
+
+  std::shared_ptr<ColorChannelDistortion> distortion_r(
+      new PolynomialRadialDistortion(poly_offsets[0], poly_r));
+  std::shared_ptr<ColorChannelDistortion> distortion_g(
+      new PolynomialRadialDistortion(poly_offsets[1], poly_g));
+  std::shared_ptr<ColorChannelDistortion> distortion_b(
+      new PolynomialRadialDistortion(poly_offsets[2], poly_b));
+
+  return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(),
+                          GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
+                          r_fov, distortion_r, distortion_g, distortion_b,
+                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
+                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
+                          (GetInterLensDistance() - GetDisplayGap()) / 2.0f);
+}
+
+HeadMountMetrics CreateHeadMountMetrics() {
+  std::vector<float> fovs = GetMaxFOVs();
+  FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]);
+  FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]);
+  return CreateHeadMountMetrics(l_fov, r_fov);
+}
+
+DisplayMetrics CreateDisplayMetrics(vec2i screen_size) {
+  android::dvr::vec2 size_in_meters = GetDisplaySize();
+  vec2 meters_per_pixel(size_in_meters[0] / static_cast<float>(screen_size[0]),
+                        size_in_meters[1] / static_cast<float>(screen_size[1]));
+  return DisplayMetrics(screen_size, meters_per_pixel, kScreenBorderSize,
+                        1000.0f / kScreenRefreshRate, kDisplayOrientation);
+}
+
+HeadMountMetrics CreateUndistortedHeadMountMetrics() {
+  std::vector<float> fovs = GetMaxFOVs();
+  FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]);
+  FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]);
+  return CreateUndistortedHeadMountMetrics(l_fov, r_fov);
+}
+
+HeadMountMetrics CreateUndistortedHeadMountMetrics(const FieldOfView& l_fov,
+                                                   const FieldOfView& r_fov) {
+  auto distortion_all = std::make_shared<IdentityDistortion>();
+
+  return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(),
+                          GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
+                          r_fov, distortion_all, distortion_all, distortion_all,
+                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
+                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
+                          (GetInterLensDistance() - GetDisplayGap()) / 2.0f);
+}
+
+}  // namespace dvr
+}  // namespace android