/*
 * 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.
 */
#include "impl/vr_hwc.h"

#include <cutils/properties.h>
#include <private/dvr/display_client.h>
#include <ui/Fence.h>

#include <mutex>

#include "vr_composer_client.h"

using namespace android::hardware::graphics::common::V1_0;
using namespace android::hardware::graphics::composer::V2_1;

using android::hardware::hidl_handle;
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
using android::hardware::Return;
using android::hardware::Void;

namespace android {
namespace dvr {
namespace {

using android::hardware::graphics::common::V1_0::PixelFormat;

const Display kDefaultDisplayId = 1;
const Config kDefaultConfigId = 1;

sp<GraphicBuffer> CreateGraphicBuffer(
    const native_handle_t* handle,
    const IVrComposerClient::BufferMetadata& metadata) {
   sp<GraphicBuffer> buffer = new GraphicBuffer(
      handle, GraphicBuffer::CLONE_HANDLE, metadata.width, metadata.height,
      static_cast<int32_t>(metadata.format), metadata.layerCount,
      metadata.usage, metadata.stride);
   if (buffer->initCheck() != OK) {
     ALOGE("Failed to create graphic buffer");
     return nullptr;
   }

   return buffer;
}

void GetPrimaryDisplaySize(int32_t* width, int32_t* height) {
  *width = 1080;
  *height = 1920;

  int error = 0;
  auto display_client = display::DisplayClient::Create(&error);
  if (!display_client) {
    ALOGE("Could not connect to display service : %s(%d)", strerror(error),
          error);
    return;
  }

  auto status = display_client->GetDisplayMetrics();
  if (!status) {
    ALOGE("Could not get display metrics from display service : %s(%d)",
          status.GetErrorMessage().c_str(), status.error());
    return;
  }

  *width = status.get().display_width;
  *height = status.get().display_height;
}

}  // namespace

HwcDisplay::HwcDisplay(int32_t width, int32_t height)
    : width_(width), height_(height) {}

HwcDisplay::~HwcDisplay() {}

bool HwcDisplay::SetClientTarget(const native_handle_t* handle,
                                 base::unique_fd fence) {
  if (handle)
    buffer_ = CreateGraphicBuffer(handle, buffer_metadata_);

  fence_ = new Fence(fence.release());
  return true;
}

void HwcDisplay::SetClientTargetMetadata(
    const IVrComposerClient::BufferMetadata& metadata) {
  buffer_metadata_ = metadata;
}

HwcLayer* HwcDisplay::CreateLayer() {
  uint64_t layer_id = layer_ids_++;
  layers_.push_back(HwcLayer(layer_id));
  return &layers_.back();
}

HwcLayer* HwcDisplay::GetLayer(Layer id) {
  for (size_t i = 0; i < layers_.size(); ++i)
    if (layers_[i].info.id == id)
      return &layers_[i];

  return nullptr;
}

bool HwcDisplay::DestroyLayer(Layer id) {
  for (auto it = layers_.begin(); it != layers_.end(); ++it) {
    if (it->info.id == id) {
      layers_.erase(it);
      return true;
    }
  }

  return false;
}

void HwcDisplay::GetChangedCompositionTypes(
    std::vector<Layer>* layer_ids,
    std::vector<IComposerClient::Composition>* types) {
  std::sort(layers_.begin(), layers_.end(),
            [](const auto& lhs, const auto& rhs) {
              return lhs.info.z_order < rhs.info.z_order;
            });

  int first_client_layer = -1, last_client_layer = -1;
  for (size_t i = 0; i < layers_.size(); ++i) {
    switch (layers_[i].composition_type) {
      case IComposerClient::Composition::SOLID_COLOR:
      case IComposerClient::Composition::CURSOR:
      case IComposerClient::Composition::SIDEBAND:
        if (first_client_layer < 0)
          first_client_layer = i;

        last_client_layer = i;
        break;
      default:
        break;
    }
  }

  for (size_t i = 0; i < layers_.size(); ++i) {
    if (i >= first_client_layer && i <= last_client_layer) {
      if (layers_[i].composition_type != IComposerClient::Composition::CLIENT) {
        layer_ids->push_back(layers_[i].info.id);
        types->push_back(IComposerClient::Composition::CLIENT);
        layers_[i].composition_type = IComposerClient::Composition::CLIENT;
      }

      continue;
    }

    if (layers_[i].composition_type != IComposerClient::Composition::DEVICE) {
      layer_ids->push_back(layers_[i].info.id);
      types->push_back(IComposerClient::Composition::DEVICE);
      layers_[i].composition_type = IComposerClient::Composition::DEVICE;
    }
  }
}

Error HwcDisplay::GetFrame(
    std::vector<ComposerView::ComposerLayer>* out_frames) {
  bool queued_client_target = false;
  std::vector<ComposerView::ComposerLayer> frame;
  for (const auto& layer : layers_) {
    if (layer.composition_type == IComposerClient::Composition::CLIENT) {
      if (queued_client_target)
        continue;

      if (!buffer_.get()) {
        ALOGE("Client composition requested but no client target buffer");
        return Error::BAD_LAYER;
      }

      ComposerView::ComposerLayer client_target_layer = {
          .buffer = buffer_,
          .fence = fence_.get() ? fence_ : new Fence(-1),
          .display_frame = {0, 0, static_cast<int32_t>(buffer_->getWidth()),
            static_cast<int32_t>(buffer_->getHeight())},
          .crop = {0.0f, 0.0f, static_cast<float>(buffer_->getWidth()),
            static_cast<float>(buffer_->getHeight())},
          .blend_mode = IComposerClient::BlendMode::NONE,
      };

      frame.push_back(client_target_layer);
      queued_client_target = true;
    } else {
      if (!layer.info.buffer.get() || !layer.info.fence.get()) {
        ALOGV("Layer requested without valid buffer");
        continue;
      }

      frame.push_back(layer.info);
    }
  }

  out_frames->swap(frame);
  return Error::NONE;
}

std::vector<Layer> HwcDisplay::UpdateLastFrameAndGetLastFrameLayers() {
  std::vector<Layer> last_frame_layers;
  last_frame_layers.swap(last_frame_layers_ids_);

  for (const auto& layer : layers_)
    last_frame_layers_ids_.push_back(layer.info.id);

  return last_frame_layers;
}

void HwcDisplay::SetColorTransform(const float* matrix, int32_t hint) {
  color_transform_hint_ = hint;
  if (matrix)
    memcpy(color_transform_, matrix, sizeof(color_transform_));
}

////////////////////////////////////////////////////////////////////////////////
// VrHwcClient

VrHwc::VrHwc() {}

VrHwc::~VrHwc() {}

bool VrHwc::hasCapability(Capability capability) const { return false; }

void VrHwc::removeClient() {
  std::lock_guard<std::mutex> guard(mutex_);
  client_ = nullptr;
}

void VrHwc::enableCallback(bool enable) {
  if (enable && client_ != nullptr) {
    {
      int32_t width, height;
      GetPrimaryDisplaySize(&width, &height);
      std::lock_guard<std::mutex> guard(mutex_);
      // Create the primary display late to avoid initialization issues between
      // VR HWC and SurfaceFlinger.
      displays_[kDefaultDisplayId].reset(new HwcDisplay(width, height));
    }
    client_.promote()->onHotplug(kDefaultDisplayId,
                                 IComposerCallback::Connection::CONNECTED);
  }
}

uint32_t VrHwc::getMaxVirtualDisplayCount() { return 1; }

Error VrHwc::createVirtualDisplay(uint32_t width, uint32_t height,
                                  PixelFormat* format, Display* outDisplay) {
  *format = PixelFormat::RGBA_8888;
  *outDisplay = display_count_;
  displays_[display_count_].reset(new HwcDisplay(width, height));
  display_count_++;
  return Error::NONE;
}

Error VrHwc::destroyVirtualDisplay(Display display) {
  std::lock_guard<std::mutex> guard(mutex_);
  if (display == kDefaultDisplayId || displays_.erase(display) == 0)
    return Error::BAD_DISPLAY;
  ComposerView::Frame frame;
  frame.display_id = display;
  frame.removed = true;
  if (observer_)
    observer_->OnNewFrame(frame);
  return Error::NONE;
}

Error VrHwc::createLayer(Display display, Layer* outLayer) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* layer = display_ptr->CreateLayer();
  *outLayer = layer->info.id;
  return Error::NONE;
}

Error VrHwc::destroyLayer(Display display, Layer layer) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr) {
    return Error::BAD_DISPLAY;
  }

  return display_ptr->DestroyLayer(layer) ? Error::NONE : Error::BAD_LAYER;
}

Error VrHwc::getActiveConfig(Display display, Config* outConfig) {
  std::lock_guard<std::mutex> guard(mutex_);
  if (!FindDisplay(display))
    return Error::BAD_DISPLAY;
  *outConfig = kDefaultConfigId;
  return Error::NONE;
}

Error VrHwc::getClientTargetSupport(Display display, uint32_t width,
                                    uint32_t height, PixelFormat format,
                                    Dataspace dataspace) {
  return Error::NONE;
}

Error VrHwc::getColorModes(Display display, hidl_vec<ColorMode>* outModes) {
  std::vector<ColorMode> color_modes(1, ColorMode::NATIVE);
  *outModes = hidl_vec<ColorMode>(color_modes);
  return Error::NONE;
}

Error VrHwc::getDisplayAttribute(Display display, Config config,
                                 IComposerClient::Attribute attribute,
                                 int32_t* outValue) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr) {
    return Error::BAD_DISPLAY;
  }
  if (config != kDefaultConfigId) {
    return Error::BAD_CONFIG;
  }

  switch (attribute) {
    case IComposerClient::Attribute::WIDTH:
      *outValue = display_ptr->width();
      break;
    case IComposerClient::Attribute::HEIGHT:
      *outValue = display_ptr->height();
      break;
    case IComposerClient::Attribute::VSYNC_PERIOD:
      {
        int error = 0;
        auto display_client = display::DisplayClient::Create(&error);
        if (!display_client) {
          ALOGE("Could not connect to display service : %s(%d)",
                strerror(error), error);
          // Return a default value of 30 fps
          *outValue = 1000 * 1000 * 1000 / 30;
        } else {
          auto metrics = display_client->GetDisplayMetrics();
          *outValue = metrics.get().vsync_period_ns;
        }
      }
      break;
    case IComposerClient::Attribute::DPI_X:
    case IComposerClient::Attribute::DPI_Y:
      {
        constexpr int32_t kDefaultDPI = 300;
        int32_t dpi = property_get_int32("ro.vr.hwc.dpi", kDefaultDPI);
        if (dpi <= 0) {
          dpi = kDefaultDPI;
        }
        *outValue = 1000 * dpi;
      }
      break;
    default:
      return Error::BAD_PARAMETER;
  }

  return Error::NONE;
}

Error VrHwc::getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) {
  std::lock_guard<std::mutex> guard(mutex_);
  if (!FindDisplay(display))
    return Error::BAD_DISPLAY;
  std::vector<Config> configs(1, kDefaultConfigId);
  *outConfigs = hidl_vec<Config>(configs);
  return Error::NONE;
}

Error VrHwc::getDisplayName(Display display, hidl_string* outName) {
  *outName = hidl_string();
  return Error::NONE;
}

Error VrHwc::getDisplayType(Display display,
                            IComposerClient::DisplayType* outType) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr) {
    *outType = IComposerClient::DisplayType::INVALID;
    return Error::BAD_DISPLAY;
  }

  if (display == kDefaultDisplayId)
    *outType = IComposerClient::DisplayType::PHYSICAL;
  else
    *outType = IComposerClient::DisplayType::VIRTUAL;

  return Error::NONE;
}

Error VrHwc::getDozeSupport(Display display, bool* outSupport) {
  *outSupport = false;
  std::lock_guard<std::mutex> guard(mutex_);
  if (!FindDisplay(display))
    return Error::BAD_DISPLAY;
  return Error::NONE;
}

Error VrHwc::getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
                                float* outMaxLuminance,
                                float* outMaxAverageLuminance,
                                float* outMinLuminance) {
  *outMaxLuminance = 0;
  *outMaxAverageLuminance = 0;
  *outMinLuminance = 0;
  return Error::NONE;
}

Error VrHwc::setActiveConfig(Display display, Config config) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;
  if (config != kDefaultConfigId)
    return Error::BAD_CONFIG;

  display_ptr->set_active_config(config);
  return Error::NONE;
}

Error VrHwc::setColorMode(Display display, ColorMode mode) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  display_ptr->set_color_mode(mode);
  return Error::NONE;
}

Error VrHwc::setPowerMode(Display display, IComposerClient::PowerMode mode) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  display_ptr->set_power_mode(mode);
  return Error::NONE;
}

Error VrHwc::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  display_ptr->set_vsync_enabled(enabled);
  return Error::NONE;
}

Error VrHwc::setColorTransform(Display display, const float* matrix,
                               int32_t hint) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  display_ptr->SetColorTransform(matrix, hint);
  return Error::NONE;
}

Error VrHwc::setClientTarget(Display display, buffer_handle_t target,
                             int32_t acquireFence, int32_t dataspace,
                             const std::vector<hwc_rect_t>& damage) {
  base::unique_fd fence(acquireFence);
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  if (target == nullptr)
    return Error::NONE;

  if (!display_ptr->SetClientTarget(target, std::move(fence)))
    return Error::BAD_PARAMETER;

  return Error::NONE;
}

Error VrHwc::setOutputBuffer(Display display, buffer_handle_t buffer,
                             int32_t releaseFence) {
  base::unique_fd fence(releaseFence);
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  // TODO(dnicoara): Is it necessary to do anything here?
  return Error::NONE;
}

Error VrHwc::validateDisplay(
    Display display, std::vector<Layer>* outChangedLayers,
    std::vector<IComposerClient::Composition>* outCompositionTypes,
    uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
    std::vector<uint32_t>* outRequestMasks) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  display_ptr->GetChangedCompositionTypes(outChangedLayers,
                                          outCompositionTypes);
  return Error::NONE;
}

Error VrHwc::acceptDisplayChanges(Display display) { return Error::NONE; }

Error VrHwc::presentDisplay(Display display, int32_t* outPresentFence,
                            std::vector<Layer>* outLayers,
                            std::vector<int32_t>* outReleaseFences) {
  *outPresentFence = -1;
  outLayers->clear();
  outReleaseFences->clear();

  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);

  if (!display_ptr)
    return Error::BAD_DISPLAY;

  ComposerView::Frame frame;
  std::vector<Layer> last_frame_layers;
  Error status = display_ptr->GetFrame(&frame.layers);
  frame.display_id = display;
  frame.display_width = display_ptr->width();
  frame.display_height = display_ptr->height();
  frame.active_config = display_ptr->active_config();
  frame.power_mode = display_ptr->power_mode();
  frame.vsync_enabled = display_ptr->vsync_enabled();
  frame.color_transform_hint = display_ptr->color_transform_hint();
  frame.color_mode = display_ptr->color_mode();
  memcpy(frame.color_transform, display_ptr->color_transform(),
         sizeof(frame.color_transform));
  if (status != Error::NONE)
    return status;

  last_frame_layers = display_ptr->UpdateLastFrameAndGetLastFrameLayers();

  base::unique_fd fence;
  if (observer_)
    fence = observer_->OnNewFrame(frame);

  if (fence.get() < 0)
    return Error::NONE;

  *outPresentFence = dup(fence.get());
  outLayers->swap(last_frame_layers);
  for (size_t i = 0; i < outLayers->size(); ++i)
    outReleaseFences->push_back(dup(fence.get()));

  return Error::NONE;
}

Error VrHwc::setLayerCursorPosition(Display display, Layer layer, int32_t x,
                                    int32_t y) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.cursor_x = x;
  hwc_layer->info.cursor_y = y;
  return Error::NONE;
}

Error VrHwc::setLayerBuffer(Display display, Layer layer,
                            buffer_handle_t buffer, int32_t acquireFence) {
  base::unique_fd fence(acquireFence);
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.buffer = CreateGraphicBuffer(
      buffer, hwc_layer->buffer_metadata);
  hwc_layer->info.fence = new Fence(fence.release());

  return Error::NONE;
}

Error VrHwc::setLayerSurfaceDamage(Display display, Layer layer,
                                   const std::vector<hwc_rect_t>& damage) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.damaged_regions = damage;
  return Error::NONE;
}

Error VrHwc::setLayerBlendMode(Display display, Layer layer, int32_t mode) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.blend_mode =
      static_cast<ComposerView::ComposerLayer::BlendMode>(mode);

  return Error::NONE;
}

Error VrHwc::setLayerColor(Display display, Layer layer,
                           IComposerClient::Color color) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.color = color;
  return Error::NONE;
}

Error VrHwc::setLayerCompositionType(Display display, Layer layer,
                                     int32_t type) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->composition_type = static_cast<HwcLayer::Composition>(type);

  return Error::NONE;
}

Error VrHwc::setLayerDataspace(Display display, Layer layer,
                               int32_t dataspace) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.dataspace = dataspace;
  return Error::NONE;
}

Error VrHwc::setLayerDisplayFrame(Display display, Layer layer,
                                  const hwc_rect_t& frame) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.display_frame =
      {frame.left, frame.top, frame.right, frame.bottom};

  return Error::NONE;
}

Error VrHwc::setLayerPlaneAlpha(Display display, Layer layer, float alpha) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.alpha = alpha;

  return Error::NONE;
}

Error VrHwc::setLayerSidebandStream(Display display, Layer layer,
                                    buffer_handle_t stream) {
  std::lock_guard<std::mutex> guard(mutex_);
  if (!FindDisplay(display))
    return Error::BAD_DISPLAY;
  return Error::NONE;
}

Error VrHwc::setLayerSourceCrop(Display display, Layer layer,
                                const hwc_frect_t& crop) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.crop = {crop.left, crop.top, crop.right, crop.bottom};

  return Error::NONE;
}

Error VrHwc::setLayerTransform(Display display, Layer layer,
                               int32_t transform) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.transform = transform;
  return Error::NONE;
}

Error VrHwc::setLayerVisibleRegion(Display display, Layer layer,
                                   const std::vector<hwc_rect_t>& visible) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.visible_regions = visible;
  return Error::NONE;
}

Error VrHwc::setLayerZOrder(Display display, Layer layer, uint32_t z) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.z_order = z;

  return Error::NONE;
}

Error VrHwc::setLayerInfo(Display display, Layer layer, uint32_t type,
                          uint32_t appId) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->info.type = type;
  hwc_layer->info.app_id = appId;

  return Error::NONE;
}

Error VrHwc::setClientTargetMetadata(
    Display display, const IVrComposerClient::BufferMetadata& metadata) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  display_ptr->SetClientTargetMetadata(metadata);

  return Error::NONE;
}

Error VrHwc::setLayerBufferMetadata(
    Display display, Layer layer,
    const IVrComposerClient::BufferMetadata& metadata) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto display_ptr = FindDisplay(display);
  if (!display_ptr)
    return Error::BAD_DISPLAY;

  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
  if (!hwc_layer)
    return Error::BAD_LAYER;

  hwc_layer->buffer_metadata = metadata;

  return Error::NONE;
}

Return<void> VrHwc::getCapabilities(getCapabilities_cb hidl_cb) {
  hidl_cb(hidl_vec<Capability>());
  return Void();
}

Return<void> VrHwc::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
  hidl_cb(hidl_string());
  return Void();
}

Return<void> VrHwc::createClient(createClient_cb hidl_cb) {
  std::lock_guard<std::mutex> guard(mutex_);

  Error status = Error::NONE;
  sp<VrComposerClient> client;
  if (client_ == nullptr) {
    client = new VrComposerClient(*this);
  } else {
    ALOGE("Already have a client");
    status = Error::NO_RESOURCES;
  }

  client_ = client;
  hidl_cb(status, client);
  return Void();
}

void VrHwc::RegisterObserver(Observer* observer) {
  std::lock_guard<std::mutex> guard(mutex_);
  if (observer_)
    ALOGE("Overwriting observer");
  else
    observer_ = observer;
}

void VrHwc::UnregisterObserver(Observer* observer) {
  std::lock_guard<std::mutex> guard(mutex_);
  if (observer != observer_)
    ALOGE("Trying to unregister unknown observer");
  else
    observer_ = nullptr;
}

HwcDisplay* VrHwc::FindDisplay(Display display) {
  auto iter = displays_.find(display);
  return iter == displays_.end() ? nullptr : iter->second.get();
}

}  // namespace dvr
}  // namespace android
