#include "display_surface.h"

#include <private/android_filesystem_config.h>
#include <utils/Trace.h>

#include <private/dvr/trusted_uids.h>

#include "display_service.h"
#include "hardware_composer.h"

#define LOCAL_TRACE 1

using android::dvr::display::DisplayProtocol;
using android::pdx::BorrowedChannelHandle;
using android::pdx::ErrorStatus;
using android::pdx::LocalChannelHandle;
using android::pdx::LocalHandle;
using android::pdx::Message;
using android::pdx::RemoteChannelHandle;
using android::pdx::Status;
using android::pdx::rpc::DispatchRemoteMethod;
using android::pdx::rpc::IfAnyOf;

namespace android {
namespace dvr {

DisplaySurface::DisplaySurface(DisplayService* service,
                               SurfaceType surface_type, int surface_id,
                               int process_id, int user_id,
                               const display::SurfaceAttributes& attributes)
    : service_(service),
      surface_type_(surface_type),
      surface_id_(surface_id),
      process_id_(process_id),
      user_id_(user_id),
      attributes_(attributes),
      update_flags_(display::SurfaceUpdateFlags::NewSurface) {}

DisplaySurface::~DisplaySurface() {
  ALOGD_IF(LOCAL_TRACE,
           "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
           surface_id(), process_id());
}

Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
  switch (message.GetOp()) {
    case DisplayProtocol::SetAttributes::Opcode:
      DispatchRemoteMethod<DisplayProtocol::SetAttributes>(
          *this, &DisplaySurface::OnSetAttributes, message);
      break;

    case DisplayProtocol::GetSurfaceInfo::Opcode:
      DispatchRemoteMethod<DisplayProtocol::GetSurfaceInfo>(
          *this, &DisplaySurface::OnGetSurfaceInfo, message);
      break;

    case DisplayProtocol::CreateQueue::Opcode:
      DispatchRemoteMethod<DisplayProtocol::CreateQueue>(
          *this, &DisplaySurface::OnCreateQueue, message);
      break;
  }

  return {};
}

Status<void> DisplaySurface::OnSetAttributes(
    pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) {
  display::SurfaceUpdateFlags update_flags;

  for (const auto& attribute : attributes) {
    const auto& key = attribute.first;
    const auto* variant = &attribute.second;
    bool invalid_value = false;
    bool visibility_changed = false;

    // Catch attributes that have significance to the display service.
    switch (key) {
      case display::SurfaceAttribute::ZOrder:
        invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
            variant, [&](const auto& value) {
              if (z_order_ != value) {
                visibility_changed = true;
                z_order_ = value;
              }
            });
        break;
      case display::SurfaceAttribute::Visible:
        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
            variant, [&](const auto& value) {
              if (visible_ != value) {
                visibility_changed = true;
                visible_ = value;
              }
            });
        break;
    }

    if (invalid_value) {
      ALOGW(
          "DisplaySurface::OnClientSetAttributes: Failed to set display "
          "surface attribute '%d' because of incompatible type: %d",
          key, variant->index());
    } else {
      // Only update the attribute map with valid values.
      attributes_[attribute.first] = attribute.second;

      // All attribute changes generate a notification, even if the value
      // doesn't change. Visibility attributes set a flag only if the value
      // changes.
      update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged);
      if (visibility_changed)
        update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged);
    }
  }

  SurfaceUpdated(update_flags);
  return {};
}

void DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) {
  ALOGD_IF(TRACE,
           "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x",
           surface_id(), update_flags.value());

  update_flags_.Set(update_flags);
  service()->SurfaceUpdated(surface_type(), update_flags_);
}

void DisplaySurface::ClearUpdate() {
  ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id());
  update_flags_ = display::SurfaceUpdateFlags::None;
}

Status<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo(
    Message& /*message*/) {
  ALOGD_IF(
      TRACE,
      "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d",
      surface_id(), visible(), z_order());
  return {{surface_id(), visible(), z_order()}};
}

Status<void> DisplaySurface::RegisterQueue(
    const std::shared_ptr<ConsumerQueue>& consumer_queue) {
  ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d",
           surface_id(), consumer_queue->id());
  // Capture references for the lambda to work around apparent clang bug.
  // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when
  // capturing self and consumer_queue by copy in the following case:
  //    auto self = Self();
  //    [self, consumer_queue](int events) {
  //        self->OnQueueEvent(consuemr_queue, events); }
  //
  struct State {
    std::shared_ptr<DisplaySurface> surface;
    std::shared_ptr<ConsumerQueue> queue;
  };
  State state{Self(), consumer_queue};

  return service()->AddEventHandler(
      consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET,
      [state](int events) {
        state.surface->OnQueueEvent(state.queue, events);
      });
}

Status<void> DisplaySurface::UnregisterQueue(
    const std::shared_ptr<ConsumerQueue>& consumer_queue) {
  ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d",
           surface_id(), consumer_queue->id());
  return service()->RemoveEventHandler(consumer_queue->queue_fd());
}

void DisplaySurface::OnQueueEvent(
    const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) {
  ALOGE(
      "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be "
      "called!!!");
}

std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
    int32_t queue_id) {
  ALOGD_IF(TRACE,
           "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
           surface_id(), queue_id);

  auto search = consumer_queues_.find(queue_id);
  if (search != consumer_queues_.end())
    return search->second;
  else
    return nullptr;
}

std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
  std::vector<int32_t> queue_ids;
  for (const auto& entry : consumer_queues_)
    queue_ids.push_back(entry.first);
  return queue_ids;
}

Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
    Message& /*message*/, size_t meta_size_bytes) {
  ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
  ALOGD_IF(TRACE,
           "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
           "meta_size_bytes=%zu",
           surface_id(), meta_size_bytes);

  std::lock_guard<std::mutex> autolock(lock_);
  auto producer = ProducerQueue::Create(meta_size_bytes);
  if (!producer) {
    ALOGE(
        "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
        "queue!");
    return ErrorStatus(ENOMEM);
  }

  std::shared_ptr<ConsumerQueue> consumer =
      producer->CreateSilentConsumerQueue();
  auto status = RegisterQueue(consumer);
  if (!status) {
    ALOGE(
        "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer "
        "queue: %s",
        status.GetErrorMessage().c_str());
    return status.error_status();
  }

  consumer_queues_[consumer->id()] = std::move(consumer);

  SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
  return std::move(producer->GetChannelHandle());
}

void ApplicationDisplaySurface::OnQueueEvent(
    const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
  ALOGD_IF(TRACE,
           "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
           consumer_queue->id(), events);

  // Always give the queue a chance to handle its internal bookkeeping.
  consumer_queue->HandleQueueEvents();

  // Check for hangup and remove a queue that is no longer needed.
  std::lock_guard<std::mutex> autolock(lock_);
  if (consumer_queue->hung_up()) {
    ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue.");
    UnregisterQueue(consumer_queue);
    auto search = consumer_queues_.find(consumer_queue->id());
    if (search != consumer_queues_.end()) {
      consumer_queues_.erase(search);
    } else {
      ALOGE(
          "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d",
          consumer_queue->id());
    }
    SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
  }
}

Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
    Message& /*message*/, size_t meta_size_bytes) {
  ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
  ALOGD_IF(
      TRACE,
      "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
      surface_id(), meta_size_bytes);

  std::lock_guard<std::mutex> autolock(lock_);
  if (!direct_queue_) {
    auto producer = ProducerQueue::Create(meta_size_bytes);
    if (!producer) {
      ALOGE(
          "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
          "queue!");
      return ErrorStatus(ENOMEM);
    }

    direct_queue_ = producer->CreateConsumerQueue();
    auto status = RegisterQueue(direct_queue_);
    if (!status) {
      ALOGE(
          "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
          "queue: %s",
          status.GetErrorMessage().c_str());
      return status.error_status();
    }

    return std::move(producer->GetChannelHandle());
  } else {
    return ErrorStatus(EALREADY);
  }
}

void DirectDisplaySurface::OnQueueEvent(
    const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
  ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
           consumer_queue->id(), events);

  // Always give the queue a chance to handle its internal bookkeeping.
  consumer_queue->HandleQueueEvents();

  // Check for hangup and remove a queue that is no longer needed.
  std::lock_guard<std::mutex> autolock(lock_);
  if (consumer_queue->hung_up()) {
    ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
    UnregisterQueue(consumer_queue);
    direct_queue_ = nullptr;
  }
}

void DirectDisplaySurface::DequeueBuffersLocked() {
  if (direct_queue_ == nullptr) {
    ALOGE(
        "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
        "initialized.");
    return;
  }

  while (true) {
    LocalHandle acquire_fence;
    size_t slot;
    auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
    if (!buffer_status) {
      ALOGD_IF(
          TRACE && buffer_status.error() == ETIMEDOUT,
          "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
      ALOGE_IF(buffer_status.error() != ETIMEDOUT,
               "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
               "buffer: %s",
               buffer_status.GetErrorMessage().c_str());
      return;
    }
    auto buffer_consumer = buffer_status.take();

    if (!visible()) {
      ATRACE_NAME("DropFrameOnInvisibleSurface");
      ALOGD_IF(TRACE,
               "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
               "buffer_id=%d on invisible surface.",
               buffer_consumer->id());
      buffer_consumer->Discard();
      continue;
    }

    if (acquired_buffers_.IsFull()) {
      ALOGE(
          "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
          "overwriting.");
      acquired_buffers_.PopBack();
    }

    acquired_buffers_.Append(
        AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
  }
}

AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
  std::lock_guard<std::mutex> autolock(lock_);
  DequeueBuffersLocked();

  if (acquired_buffers_.IsEmpty()) {
    ALOGE(
        "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
        "when none are posted.");
    return AcquiredBuffer();
  }
  AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
  acquired_buffers_.PopFront();
  ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p",
           buffer.buffer().get());
  return buffer;
}

AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
    AcquiredBuffer* skipped_buffer) {
  std::lock_guard<std::mutex> autolock(lock_);
  DequeueBuffersLocked();

  AcquiredBuffer buffer;
  int frames = 0;
  // Basic latency stopgap for when the application misses a frame:
  // If the application recovers on the 2nd or 3rd (etc) frame after
  // missing, this code will skip frames to catch up by checking if
  // the next frame is also available.
  while (!acquired_buffers_.IsEmpty() &&
         acquired_buffers_.Front().IsAvailable()) {
    // Capture the skipped buffer into the result parameter.
    // Note that this API only supports skipping one buffer per vsync.
    if (frames > 0 && skipped_buffer)
      *skipped_buffer = std::move(buffer);
    ++frames;
    buffer = std::move(acquired_buffers_.Front());
    acquired_buffers_.PopFront();
    if (frames == 2)
      break;
  }
  ALOGD_IF(TRACE,
           "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
           buffer.buffer().get());
  return buffer;
}

bool DirectDisplaySurface::IsBufferAvailable() {
  std::lock_guard<std::mutex> autolock(lock_);
  DequeueBuffersLocked();

  return !acquired_buffers_.IsEmpty() &&
         acquired_buffers_.Front().IsAvailable();
}

bool DirectDisplaySurface::IsBufferPosted() {
  std::lock_guard<std::mutex> autolock(lock_);
  DequeueBuffersLocked();

  return !acquired_buffers_.IsEmpty();
}

Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
    DisplayService* service, int surface_id, int process_id, int user_id,
    const display::SurfaceAttributes& attributes) {
  bool direct = false;
  auto search = attributes.find(display::SurfaceAttribute::Direct);
  if (search != attributes.end()) {
    if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
                                                     &direct)) {
      ALOGE(
          "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
      return ErrorStatus(EINVAL);
    }
  }

  ALOGD_IF(TRACE,
           "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
           "direct=%d",
           surface_id, process_id, user_id, direct);

  if (direct) {
    const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
    if (trusted) {
      return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
          service, surface_id, process_id, user_id, attributes)}};
    } else {
      ALOGE(
          "DisplaySurface::Create: Direct surfaces may only be created by "
          "trusted UIDs: user_id=%d",
          user_id);
      return ErrorStatus(EPERM);
    }
  } else {
    return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
        service, surface_id, process_id, user_id, attributes)}};
  }
}

}  // namespace dvr
}  // namespace android
