1a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include "display_surface.h"
2a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
32251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <private/android_filesystem_config.h>
4a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <utils/Trace.h>
5a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
62251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <private/dvr/trusted_uids.h>
7a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include "display_service.h"
9a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include "hardware_composer.h"
10a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
11a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#define LOCAL_TRACE 1
12a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing android::dvr::display::DisplayProtocol;
14a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::BorrowedChannelHandle;
152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing android::pdx::ErrorStatus;
16a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::LocalChannelHandle;
172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing android::pdx::LocalHandle;
18a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::Message;
19a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::RemoteChannelHandle;
20a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::Status;
21a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::rpc::DispatchRemoteMethod;
22a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::rpc::IfAnyOf;
23a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
24a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkonamespace android {
25a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkonamespace dvr {
26a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaDisplaySurface::DisplaySurface(DisplayService* service,
282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                               SurfaceType surface_type, int surface_id,
292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                               int process_id, int user_id,
302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                               const display::SurfaceAttributes& attributes)
312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    : service_(service),
322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      surface_type_(surface_type),
332251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      surface_id_(surface_id),
34a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      process_id_(process_id),
352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      user_id_(user_id),
362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      attributes_(attributes),
372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
38a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
39a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex VakulenkoDisplaySurface::~DisplaySurface() {
40a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ALOGD_IF(LOCAL_TRACE,
41a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko           "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
422251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           surface_id(), process_id());
43a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
44a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<void> DisplaySurface::HandleMessage(pdx::Message& message) {
462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  switch (message.GetOp()) {
472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    case DisplayProtocol::SetAttributes::Opcode:
482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      DispatchRemoteMethod<DisplayProtocol::SetAttributes>(
492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          *this, &DisplaySurface::OnSetAttributes, message);
502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      break;
512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    case DisplayProtocol::GetSurfaceInfo::Opcode:
532251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      DispatchRemoteMethod<DisplayProtocol::GetSurfaceInfo>(
542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          *this, &DisplaySurface::OnGetSurfaceInfo, message);
552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      break;
562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    case DisplayProtocol::CreateQueue::Opcode:
582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      DispatchRemoteMethod<DisplayProtocol::CreateQueue>(
592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          *this, &DisplaySurface::OnCreateQueue, message);
602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      break;
612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return {};
64a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
65a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<void> DisplaySurface::OnSetAttributes(
672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) {
682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  display::SurfaceUpdateFlags update_flags;
692251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
702251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  for (const auto& attribute : attributes) {
712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const auto& key = attribute.first;
722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const auto* variant = &attribute.second;
732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    bool invalid_value = false;
742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    bool visibility_changed = false;
752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    // Catch attributes that have significance to the display service.
772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    switch (key) {
782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      case display::SurfaceAttribute::ZOrder:
792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka            variant, [&](const auto& value) {
812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka              if (z_order_ != value) {
822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                visibility_changed = true;
832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                z_order_ = value;
842251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka              }
852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka            });
862251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        break;
872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      case display::SurfaceAttribute::Visible:
882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka            variant, [&](const auto& value) {
902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka              if (visible_ != value) {
912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                visibility_changed = true;
922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                visible_ = value;
932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka              }
942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka            });
952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        break;
962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    }
972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
982251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (invalid_value) {
992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGW(
1002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "DisplaySurface::OnClientSetAttributes: Failed to set display "
1012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "surface attribute '%d' because of incompatible type: %d",
1022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          key, variant->index());
1032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    } else {
1042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // Only update the attribute map with valid values.
1052251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      attributes_[attribute.first] = attribute.second;
1062251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1072251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // All attribute changes generate a notification, even if the value
1082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // doesn't change. Visibility attributes set a flag only if the value
1092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // changes.
1102251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged);
1112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      if (visibility_changed)
1122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged);
1132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    }
1142251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
1152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1162251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  SurfaceUpdated(update_flags);
1172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return {};
118a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
119a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1202251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) {
1212251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE,
1222251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x",
1232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           surface_id(), update_flags.value());
1242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  update_flags_.Set(update_flags);
1262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  service()->SurfaceUpdated(surface_type(), update_flags_);
1272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
1282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid DisplaySurface::ClearUpdate() {
1302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id());
1312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  update_flags_ = display::SurfaceUpdateFlags::None;
132a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
133a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo(
1352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    Message& /*message*/) {
1362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(
1372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      TRACE,
1382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d",
1392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      surface_id(), visible(), z_order());
1402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return {{surface_id(), visible(), z_order()}};
1412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
1422251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1432251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<void> DisplaySurface::RegisterQueue(
1442251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const std::shared_ptr<ConsumerQueue>& consumer_queue) {
1452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d",
1462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           surface_id(), consumer_queue->id());
1472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Capture references for the lambda to work around apparent clang bug.
1482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when
1492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // capturing self and consumer_queue by copy in the following case:
1502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  //    auto self = Self();
1512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  //    [self, consumer_queue](int events) {
1522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  //        self->OnQueueEvent(consuemr_queue, events); }
1532251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  //
1542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  struct State {
1552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    std::shared_ptr<DisplaySurface> surface;
1562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    std::shared_ptr<ConsumerQueue> queue;
1572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  };
1582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  State state{Self(), consumer_queue};
1592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return service()->AddEventHandler(
1612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET,
1622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      [state](int events) {
1632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        state.surface->OnQueueEvent(state.queue, events);
1642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      });
1652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
1662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<void> DisplaySurface::UnregisterQueue(
1682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const std::shared_ptr<ConsumerQueue>& consumer_queue) {
1692251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d",
1702251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           surface_id(), consumer_queue->id());
1712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return service()->RemoveEventHandler(consumer_queue->queue_fd());
1722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
1732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid DisplaySurface::OnQueueEvent(
1752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) {
1762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE(
1772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be "
1782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      "called!!!");
1792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
1802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakastd::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
1822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    int32_t queue_id) {
1832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE,
1842251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
1852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           surface_id(), queue_id);
1862251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto search = consumer_queues_.find(queue_id);
1882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (search != consumer_queues_.end())
1892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return search->second;
1902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  else
1912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return nullptr;
1922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
1932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakastd::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
1952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  std::vector<int32_t> queue_ids;
1962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  for (const auto& entry : consumer_queues_)
1972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    queue_ids.push_back(entry.first);
1982251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return queue_ids;
1992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
2002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
2022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    Message& /*message*/, size_t meta_size_bytes) {
2032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
2042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE,
2052251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
2062251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "meta_size_bytes=%zu",
2072251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           surface_id(), meta_size_bytes);
2082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
209a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::lock_guard<std::mutex> autolock(lock_);
2102251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto producer = ProducerQueue::Create(meta_size_bytes);
2112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (!producer) {
2122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
2132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
2142251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "queue!");
2152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return ErrorStatus(ENOMEM);
2162251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
2172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2182251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  std::shared_ptr<ConsumerQueue> consumer =
2192251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      producer->CreateSilentConsumerQueue();
2202251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto status = RegisterQueue(consumer);
2212251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (!status) {
2222251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
2232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer "
2242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "queue: %s",
2252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        status.GetErrorMessage().c_str());
2262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return status.error_status();
2272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
2282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  consumer_queues_[consumer->id()] = std::move(consumer);
2302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
2322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return std::move(producer->GetChannelHandle());
233a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
234a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
2352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid ApplicationDisplaySurface::OnQueueEvent(
2362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
2372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE,
2382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
2392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           consumer_queue->id(), events);
2402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Always give the queue a chance to handle its internal bookkeeping.
2422251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  consumer_queue->HandleQueueEvents();
2432251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2442251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Check for hangup and remove a queue that is no longer needed.
245a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::lock_guard<std::mutex> autolock(lock_);
2462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (consumer_queue->hung_up()) {
2472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue.");
2482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    UnregisterQueue(consumer_queue);
2492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    auto search = consumer_queues_.find(consumer_queue->id());
2502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (search != consumer_queues_.end()) {
2512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      consumer_queues_.erase(search);
2522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    } else {
2532251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGE(
2542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d",
2552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          consumer_queue->id());
2562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    }
2572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
2582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
259a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
260a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
2612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
2622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    Message& /*message*/, size_t meta_size_bytes) {
2632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
2642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(
2652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      TRACE,
2662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
2672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      surface_id(), meta_size_bytes);
2682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
269a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::lock_guard<std::mutex> autolock(lock_);
2702251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (!direct_queue_) {
2712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    auto producer = ProducerQueue::Create(meta_size_bytes);
2722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (!producer) {
2732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGE(
2742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
2752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "queue!");
2762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      return ErrorStatus(ENOMEM);
2772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    }
2782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    direct_queue_ = producer->CreateConsumerQueue();
2802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    auto status = RegisterQueue(direct_queue_);
2812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (!status) {
2822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGE(
2832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
2842251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "queue: %s",
2852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          status.GetErrorMessage().c_str());
2862251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      return status.error_status();
2872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    }
2882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return std::move(producer->GetChannelHandle());
2902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  } else {
2912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return ErrorStatus(EALREADY);
2922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
293a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
294a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
2952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid DirectDisplaySurface::OnQueueEvent(
2962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
2972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
2982251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           consumer_queue->id(), events);
2992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
3002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Always give the queue a chance to handle its internal bookkeeping.
3012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  consumer_queue->HandleQueueEvents();
3022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
3032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Check for hangup and remove a queue that is no longer needed.
304a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::lock_guard<std::mutex> autolock(lock_);
3052251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (consumer_queue->hung_up()) {
3062251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
3072251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    UnregisterQueue(consumer_queue);
3082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    direct_queue_ = nullptr;
3092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
310a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
311a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid DirectDisplaySurface::DequeueBuffersLocked() {
3132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (direct_queue_ == nullptr) {
314a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    ALOGE(
3152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
316a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai        "initialized.");
317a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    return;
318a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  }
319a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai
320a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  while (true) {
321a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    LocalHandle acquire_fence;
3222251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    size_t slot;
3232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
3242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (!buffer_status) {
3252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGD_IF(
3262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          TRACE && buffer_status.error() == ETIMEDOUT,
3272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
3282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGE_IF(buffer_status.error() != ETIMEDOUT,
3292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
3302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               "buffer: %s",
3312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               buffer_status.GetErrorMessage().c_str());
332a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai      return;
333a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    }
3342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    auto buffer_consumer = buffer_status.take();
335a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai
3362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (!visible()) {
337a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai      ATRACE_NAME("DropFrameOnInvisibleSurface");
338a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai      ALOGD_IF(TRACE,
3392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
3402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               "buffer_id=%d on invisible surface.",
341a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai               buffer_consumer->id());
342a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai      buffer_consumer->Discard();
343a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai      continue;
344a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    }
345a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai
346a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    if (acquired_buffers_.IsFull()) {
347a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai      ALOGE(
3482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
349a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai          "overwriting.");
350a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai      acquired_buffers_.PopBack();
351a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    }
352a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai
353a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    acquired_buffers_.Append(
3542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
355a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  }
356a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai}
357a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai
3582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaAcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
359a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  std::lock_guard<std::mutex> autolock(lock_);
360a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  DequeueBuffersLocked();
361a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai
362a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  if (acquired_buffers_.IsEmpty()) {
363a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    ALOGE(
3642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
3652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "when none are posted.");
366a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    return AcquiredBuffer();
367a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  }
368a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
369a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  acquired_buffers_.PopFront();
3702251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p",
371a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai           buffer.buffer().get());
372a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  return buffer;
373a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai}
374a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai
3752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaAcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
376a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    AcquiredBuffer* skipped_buffer) {
377a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::lock_guard<std::mutex> autolock(lock_);
378a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  DequeueBuffersLocked();
379a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai
380a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  AcquiredBuffer buffer;
381a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int frames = 0;
382a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Basic latency stopgap for when the application misses a frame:
383a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // If the application recovers on the 2nd or 3rd (etc) frame after
384a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // missing, this code will skip frames to catch up by checking if
385a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // the next frame is also available.
386a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  while (!acquired_buffers_.IsEmpty() &&
387a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai         acquired_buffers_.Front().IsAvailable()) {
388a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // Capture the skipped buffer into the result parameter.
389a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // Note that this API only supports skipping one buffer per vsync.
390a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    if (frames > 0 && skipped_buffer)
391a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      *skipped_buffer = std::move(buffer);
392a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ++frames;
393a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    buffer = std::move(acquired_buffers_.Front());
394a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai    acquired_buffers_.PopFront();
395a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    if (frames == 2)
396a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      break;
397a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
3982251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE,
3992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
400a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai           buffer.buffer().get());
401a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  return buffer;
402a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
403a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
4042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakabool DirectDisplaySurface::IsBufferAvailable() {
405a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::lock_guard<std::mutex> autolock(lock_);
406a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  DequeueBuffersLocked();
407a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
408a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  return !acquired_buffers_.IsEmpty() &&
409a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai         acquired_buffers_.Front().IsAvailable();
410a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
411a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
4122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakabool DirectDisplaySurface::IsBufferPosted() {
413a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::lock_guard<std::mutex> autolock(lock_);
414a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  DequeueBuffersLocked();
415a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
416a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  return !acquired_buffers_.IsEmpty();
417a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
418a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
4192251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
4202251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    DisplayService* service, int surface_id, int process_id, int user_id,
4212251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const display::SurfaceAttributes& attributes) {
4222251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  bool direct = false;
4232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto search = attributes.find(display::SurfaceAttribute::Direct);
4242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (search != attributes.end()) {
4252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
4262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                                     &direct)) {
4272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGE(
4282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
4292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      return ErrorStatus(EINVAL);
430a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
431a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
432a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
4332251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE,
4342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
4352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "direct=%d",
4362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           surface_id, process_id, user_id, direct);
437a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
4382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (direct) {
4392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
4402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (trusted) {
4412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
4422251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          service, surface_id, process_id, user_id, attributes)}};
443a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    } else {
4442251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGE(
4452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "DisplaySurface::Create: Direct surfaces may only be created by "
4462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "trusted UIDs: user_id=%d",
4472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          user_id);
4482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      return ErrorStatus(EPERM);
449a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
4502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  } else {
4512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
4522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        service, surface_id, process_id, user_id, attributes)}};
453a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
454a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
455a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
456a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}  // namespace dvr
457a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}  // namespace android
458