Home | History | Annotate | Download | only in libvrflinger
      1 #include "display_surface.h"
      2 
      3 #include <private/android_filesystem_config.h>
      4 #include <utils/Trace.h>
      5 
      6 #include <private/dvr/trusted_uids.h>
      7 
      8 #include "display_service.h"
      9 #include "hardware_composer.h"
     10 
     11 #define LOCAL_TRACE 1
     12 
     13 using android::dvr::display::DisplayProtocol;
     14 using android::pdx::BorrowedChannelHandle;
     15 using android::pdx::ErrorStatus;
     16 using android::pdx::LocalChannelHandle;
     17 using android::pdx::LocalHandle;
     18 using android::pdx::Message;
     19 using android::pdx::RemoteChannelHandle;
     20 using android::pdx::Status;
     21 using android::pdx::rpc::DispatchRemoteMethod;
     22 using android::pdx::rpc::IfAnyOf;
     23 
     24 namespace android {
     25 namespace dvr {
     26 
     27 DisplaySurface::DisplaySurface(DisplayService* service,
     28                                SurfaceType surface_type, int surface_id,
     29                                int process_id, int user_id,
     30                                const display::SurfaceAttributes& attributes)
     31     : service_(service),
     32       surface_type_(surface_type),
     33       surface_id_(surface_id),
     34       process_id_(process_id),
     35       user_id_(user_id),
     36       attributes_(attributes),
     37       update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
     38 
     39 DisplaySurface::~DisplaySurface() {
     40   ALOGD_IF(LOCAL_TRACE,
     41            "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
     42            surface_id(), process_id());
     43 }
     44 
     45 Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
     46   switch (message.GetOp()) {
     47     case DisplayProtocol::SetAttributes::Opcode:
     48       DispatchRemoteMethod<DisplayProtocol::SetAttributes>(
     49           *this, &DisplaySurface::OnSetAttributes, message);
     50       break;
     51 
     52     case DisplayProtocol::GetSurfaceInfo::Opcode:
     53       DispatchRemoteMethod<DisplayProtocol::GetSurfaceInfo>(
     54           *this, &DisplaySurface::OnGetSurfaceInfo, message);
     55       break;
     56 
     57     case DisplayProtocol::CreateQueue::Opcode:
     58       DispatchRemoteMethod<DisplayProtocol::CreateQueue>(
     59           *this, &DisplaySurface::OnCreateQueue, message);
     60       break;
     61   }
     62 
     63   return {};
     64 }
     65 
     66 Status<void> DisplaySurface::OnSetAttributes(
     67     pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) {
     68   display::SurfaceUpdateFlags update_flags;
     69 
     70   for (const auto& attribute : attributes) {
     71     const auto& key = attribute.first;
     72     const auto* variant = &attribute.second;
     73     bool invalid_value = false;
     74     bool visibility_changed = false;
     75 
     76     // Catch attributes that have significance to the display service.
     77     switch (key) {
     78       case display::SurfaceAttribute::ZOrder:
     79         invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
     80             variant, [&](const auto& value) {
     81               if (z_order_ != value) {
     82                 visibility_changed = true;
     83                 z_order_ = value;
     84               }
     85             });
     86         break;
     87       case display::SurfaceAttribute::Visible:
     88         invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
     89             variant, [&](const auto& value) {
     90               if (visible_ != value) {
     91                 visibility_changed = true;
     92                 visible_ = value;
     93               }
     94             });
     95         break;
     96     }
     97 
     98     if (invalid_value) {
     99       ALOGW(
    100           "DisplaySurface::OnClientSetAttributes: Failed to set display "
    101           "surface attribute '%d' because of incompatible type: %d",
    102           key, variant->index());
    103     } else {
    104       // Only update the attribute map with valid values.
    105       attributes_[attribute.first] = attribute.second;
    106 
    107       // All attribute changes generate a notification, even if the value
    108       // doesn't change. Visibility attributes set a flag only if the value
    109       // changes.
    110       update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged);
    111       if (visibility_changed)
    112         update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged);
    113     }
    114   }
    115 
    116   SurfaceUpdated(update_flags);
    117   return {};
    118 }
    119 
    120 void DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) {
    121   ALOGD_IF(TRACE,
    122            "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x",
    123            surface_id(), update_flags.value());
    124 
    125   update_flags_.Set(update_flags);
    126   service()->SurfaceUpdated(surface_type(), update_flags_);
    127 }
    128 
    129 void DisplaySurface::ClearUpdate() {
    130   ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id());
    131   update_flags_ = display::SurfaceUpdateFlags::None;
    132 }
    133 
    134 Status<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo(
    135     Message& /*message*/) {
    136   ALOGD_IF(
    137       TRACE,
    138       "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d",
    139       surface_id(), visible(), z_order());
    140   return {{surface_id(), visible(), z_order()}};
    141 }
    142 
    143 Status<void> DisplaySurface::RegisterQueue(
    144     const std::shared_ptr<ConsumerQueue>& consumer_queue) {
    145   ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d",
    146            surface_id(), consumer_queue->id());
    147   // Capture references for the lambda to work around apparent clang bug.
    148   // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when
    149   // capturing self and consumer_queue by copy in the following case:
    150   //    auto self = Self();
    151   //    [self, consumer_queue](int events) {
    152   //        self->OnQueueEvent(consuemr_queue, events); }
    153   //
    154   struct State {
    155     std::shared_ptr<DisplaySurface> surface;
    156     std::shared_ptr<ConsumerQueue> queue;
    157   };
    158   State state{Self(), consumer_queue};
    159 
    160   return service()->AddEventHandler(
    161       consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET,
    162       [state](int events) {
    163         state.surface->OnQueueEvent(state.queue, events);
    164       });
    165 }
    166 
    167 Status<void> DisplaySurface::UnregisterQueue(
    168     const std::shared_ptr<ConsumerQueue>& consumer_queue) {
    169   ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d",
    170            surface_id(), consumer_queue->id());
    171   return service()->RemoveEventHandler(consumer_queue->queue_fd());
    172 }
    173 
    174 void DisplaySurface::OnQueueEvent(
    175     const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) {
    176   ALOGE(
    177       "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be "
    178       "called!!!");
    179 }
    180 
    181 std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
    182     int32_t queue_id) {
    183   ALOGD_IF(TRACE,
    184            "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
    185            surface_id(), queue_id);
    186 
    187   auto search = consumer_queues_.find(queue_id);
    188   if (search != consumer_queues_.end())
    189     return search->second;
    190   else
    191     return nullptr;
    192 }
    193 
    194 std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
    195   std::vector<int32_t> queue_ids;
    196   for (const auto& entry : consumer_queues_)
    197     queue_ids.push_back(entry.first);
    198   return queue_ids;
    199 }
    200 
    201 Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
    202     Message& /*message*/, size_t meta_size_bytes) {
    203   ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
    204   ALOGD_IF(TRACE,
    205            "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
    206            "meta_size_bytes=%zu",
    207            surface_id(), meta_size_bytes);
    208 
    209   std::lock_guard<std::mutex> autolock(lock_);
    210   auto producer = ProducerQueue::Create(meta_size_bytes);
    211   if (!producer) {
    212     ALOGE(
    213         "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
    214         "queue!");
    215     return ErrorStatus(ENOMEM);
    216   }
    217 
    218   std::shared_ptr<ConsumerQueue> consumer =
    219       producer->CreateSilentConsumerQueue();
    220   auto status = RegisterQueue(consumer);
    221   if (!status) {
    222     ALOGE(
    223         "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer "
    224         "queue: %s",
    225         status.GetErrorMessage().c_str());
    226     return status.error_status();
    227   }
    228 
    229   consumer_queues_[consumer->id()] = std::move(consumer);
    230 
    231   SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
    232   return std::move(producer->GetChannelHandle());
    233 }
    234 
    235 void ApplicationDisplaySurface::OnQueueEvent(
    236     const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
    237   ALOGD_IF(TRACE,
    238            "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
    239            consumer_queue->id(), events);
    240 
    241   // Always give the queue a chance to handle its internal bookkeeping.
    242   consumer_queue->HandleQueueEvents();
    243 
    244   // Check for hangup and remove a queue that is no longer needed.
    245   std::lock_guard<std::mutex> autolock(lock_);
    246   if (consumer_queue->hung_up()) {
    247     ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue.");
    248     UnregisterQueue(consumer_queue);
    249     auto search = consumer_queues_.find(consumer_queue->id());
    250     if (search != consumer_queues_.end()) {
    251       consumer_queues_.erase(search);
    252     } else {
    253       ALOGE(
    254           "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d",
    255           consumer_queue->id());
    256     }
    257     SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
    258   }
    259 }
    260 
    261 Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
    262     Message& /*message*/, size_t meta_size_bytes) {
    263   ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
    264   ALOGD_IF(
    265       TRACE,
    266       "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
    267       surface_id(), meta_size_bytes);
    268 
    269   std::lock_guard<std::mutex> autolock(lock_);
    270   if (!direct_queue_) {
    271     auto producer = ProducerQueue::Create(meta_size_bytes);
    272     if (!producer) {
    273       ALOGE(
    274           "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
    275           "queue!");
    276       return ErrorStatus(ENOMEM);
    277     }
    278 
    279     direct_queue_ = producer->CreateConsumerQueue();
    280     auto status = RegisterQueue(direct_queue_);
    281     if (!status) {
    282       ALOGE(
    283           "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
    284           "queue: %s",
    285           status.GetErrorMessage().c_str());
    286       return status.error_status();
    287     }
    288 
    289     return std::move(producer->GetChannelHandle());
    290   } else {
    291     return ErrorStatus(EALREADY);
    292   }
    293 }
    294 
    295 void DirectDisplaySurface::OnQueueEvent(
    296     const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
    297   ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
    298            consumer_queue->id(), events);
    299 
    300   // Always give the queue a chance to handle its internal bookkeeping.
    301   consumer_queue->HandleQueueEvents();
    302 
    303   // Check for hangup and remove a queue that is no longer needed.
    304   std::lock_guard<std::mutex> autolock(lock_);
    305   if (consumer_queue->hung_up()) {
    306     ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
    307     UnregisterQueue(consumer_queue);
    308     direct_queue_ = nullptr;
    309   }
    310 }
    311 
    312 void DirectDisplaySurface::DequeueBuffersLocked() {
    313   if (direct_queue_ == nullptr) {
    314     ALOGE(
    315         "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
    316         "initialized.");
    317     return;
    318   }
    319 
    320   while (true) {
    321     LocalHandle acquire_fence;
    322     size_t slot;
    323     auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
    324     if (!buffer_status) {
    325       ALOGD_IF(
    326           TRACE && buffer_status.error() == ETIMEDOUT,
    327           "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
    328       ALOGE_IF(buffer_status.error() != ETIMEDOUT,
    329                "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
    330                "buffer: %s",
    331                buffer_status.GetErrorMessage().c_str());
    332       return;
    333     }
    334     auto buffer_consumer = buffer_status.take();
    335 
    336     if (!visible()) {
    337       ATRACE_NAME("DropFrameOnInvisibleSurface");
    338       ALOGD_IF(TRACE,
    339                "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
    340                "buffer_id=%d on invisible surface.",
    341                buffer_consumer->id());
    342       buffer_consumer->Discard();
    343       continue;
    344     }
    345 
    346     if (acquired_buffers_.IsFull()) {
    347       ALOGE(
    348           "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
    349           "overwriting.");
    350       acquired_buffers_.PopBack();
    351     }
    352 
    353     acquired_buffers_.Append(
    354         AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
    355   }
    356 }
    357 
    358 AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
    359   std::lock_guard<std::mutex> autolock(lock_);
    360   DequeueBuffersLocked();
    361 
    362   if (acquired_buffers_.IsEmpty()) {
    363     ALOGE(
    364         "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
    365         "when none are posted.");
    366     return AcquiredBuffer();
    367   }
    368   AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
    369   acquired_buffers_.PopFront();
    370   ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p",
    371            buffer.buffer().get());
    372   return buffer;
    373 }
    374 
    375 AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
    376     AcquiredBuffer* skipped_buffer) {
    377   std::lock_guard<std::mutex> autolock(lock_);
    378   DequeueBuffersLocked();
    379 
    380   AcquiredBuffer buffer;
    381   int frames = 0;
    382   // Basic latency stopgap for when the application misses a frame:
    383   // If the application recovers on the 2nd or 3rd (etc) frame after
    384   // missing, this code will skip frames to catch up by checking if
    385   // the next frame is also available.
    386   while (!acquired_buffers_.IsEmpty() &&
    387          acquired_buffers_.Front().IsAvailable()) {
    388     // Capture the skipped buffer into the result parameter.
    389     // Note that this API only supports skipping one buffer per vsync.
    390     if (frames > 0 && skipped_buffer)
    391       *skipped_buffer = std::move(buffer);
    392     ++frames;
    393     buffer = std::move(acquired_buffers_.Front());
    394     acquired_buffers_.PopFront();
    395     if (frames == 2)
    396       break;
    397   }
    398   ALOGD_IF(TRACE,
    399            "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
    400            buffer.buffer().get());
    401   return buffer;
    402 }
    403 
    404 bool DirectDisplaySurface::IsBufferAvailable() {
    405   std::lock_guard<std::mutex> autolock(lock_);
    406   DequeueBuffersLocked();
    407 
    408   return !acquired_buffers_.IsEmpty() &&
    409          acquired_buffers_.Front().IsAvailable();
    410 }
    411 
    412 bool DirectDisplaySurface::IsBufferPosted() {
    413   std::lock_guard<std::mutex> autolock(lock_);
    414   DequeueBuffersLocked();
    415 
    416   return !acquired_buffers_.IsEmpty();
    417 }
    418 
    419 Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
    420     DisplayService* service, int surface_id, int process_id, int user_id,
    421     const display::SurfaceAttributes& attributes) {
    422   bool direct = false;
    423   auto search = attributes.find(display::SurfaceAttribute::Direct);
    424   if (search != attributes.end()) {
    425     if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
    426                                                      &direct)) {
    427       ALOGE(
    428           "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
    429       return ErrorStatus(EINVAL);
    430     }
    431   }
    432 
    433   ALOGD_IF(TRACE,
    434            "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
    435            "direct=%d",
    436            surface_id, process_id, user_id, direct);
    437 
    438   if (direct) {
    439     const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
    440     if (trusted) {
    441       return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
    442           service, surface_id, process_id, user_id, attributes)}};
    443     } else {
    444       ALOGE(
    445           "DisplaySurface::Create: Direct surfaces may only be created by "
    446           "trusted UIDs: user_id=%d",
    447           user_id);
    448       return ErrorStatus(EPERM);
    449     }
    450   } else {
    451     return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
    452         service, surface_id, process_id, user_id, attributes)}};
    453   }
    454 }
    455 
    456 }  // namespace dvr
    457 }  // namespace android
    458