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
13using android::dvr::display::DisplayProtocol;
14using android::pdx::BorrowedChannelHandle;
15using android::pdx::ErrorStatus;
16using android::pdx::LocalChannelHandle;
17using android::pdx::LocalHandle;
18using android::pdx::Message;
19using android::pdx::RemoteChannelHandle;
20using android::pdx::Status;
21using android::pdx::rpc::DispatchRemoteMethod;
22using android::pdx::rpc::IfAnyOf;
23
24namespace android {
25namespace dvr {
26
27DisplaySurface::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
39DisplaySurface::~DisplaySurface() {
40  ALOGD_IF(LOCAL_TRACE,
41           "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
42           surface_id(), process_id());
43}
44
45Status<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
66Status<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
120void 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
129void DisplaySurface::ClearUpdate() {
130  ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id());
131  update_flags_ = display::SurfaceUpdateFlags::None;
132}
133
134Status<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
143Status<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
167Status<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
174void 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
181std::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
194std::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
201Status<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
235void 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
261Status<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
295void 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
312void 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
358AcquiredBuffer 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
375AcquiredBuffer 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
404bool 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
412bool DirectDisplaySurface::IsBufferPosted() {
413  std::lock_guard<std::mutex> autolock(lock_);
414  DequeueBuffersLocked();
415
416  return !acquired_buffers_.IsEmpty();
417}
418
419Status<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