/*
 * 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;
            });

  const size_t no_layer = std::numeric_limits<size_t>::max();
  size_t first_client_layer = no_layer, last_client_layer = no_layer;
  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 == no_layer)
          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(hwc2_capability_t /* capability */) { 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::ForceDisplaysRefresh() {
  std::lock_guard<std::mutex> guard(mutex_);
  if (client_ != nullptr) {
    for (const auto& pair : displays_)
      client_.promote()->onRefresh(pair.first);
  }
}

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
