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