OSDN Git Service

4852fabd4b9d9f9621e76724103ca583e6a4bef1
[android-x86/frameworks-native.git] / libs / vr / libvrflinger / display_surface.cpp
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     // Only update the attribute map with valid values. This check also has the
99     // effect of preventing special attributes handled above from being deleted
100     // by an empty value.
101     if (invalid_value) {
102       ALOGW(
103           "DisplaySurface::OnClientSetAttributes: Failed to set display "
104           "surface attribute '%d' because of incompatible type: %d",
105           key, variant->index());
106     } else {
107       // An empty value indicates the attribute should be deleted.
108       if (variant->empty()) {
109         auto search = attributes_.find(key);
110         if (search != attributes_.end())
111           attributes_.erase(search);
112       } else {
113         attributes_[key] = *variant;
114       }
115
116       // All attribute changes generate a notification, even if the value
117       // doesn't change. Visibility attributes set a flag only if the value
118       // changes.
119       update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged);
120       if (visibility_changed)
121         update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged);
122     }
123   }
124
125   SurfaceUpdated(update_flags);
126   return {};
127 }
128
129 void DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) {
130   ALOGD_IF(TRACE,
131            "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x",
132            surface_id(), update_flags.value());
133
134   update_flags_.Set(update_flags);
135   service()->SurfaceUpdated(surface_type(), update_flags_);
136 }
137
138 void DisplaySurface::ClearUpdate() {
139   ALOGD_IF(TRACE > 1, "DisplaySurface::ClearUpdate: surface_id=%d",
140            surface_id());
141   update_flags_ = display::SurfaceUpdateFlags::None;
142 }
143
144 Status<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo(
145     Message& /*message*/) {
146   ALOGD_IF(
147       TRACE,
148       "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d",
149       surface_id(), visible(), z_order());
150   return {{surface_id(), visible(), z_order()}};
151 }
152
153 Status<void> DisplaySurface::RegisterQueue(
154     const std::shared_ptr<ConsumerQueue>& consumer_queue) {
155   ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d",
156            surface_id(), consumer_queue->id());
157   // Capture references for the lambda to work around apparent clang bug.
158   // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when
159   // capturing self and consumer_queue by copy in the following case:
160   //    auto self = Self();
161   //    [self, consumer_queue](int events) {
162   //        self->OnQueueEvent(consuemr_queue, events); }
163   //
164   struct State {
165     std::shared_ptr<DisplaySurface> surface;
166     std::shared_ptr<ConsumerQueue> queue;
167   };
168   State state{Self(), consumer_queue};
169
170   return service()->AddEventHandler(
171       consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET,
172       [state](int events) {
173         state.surface->OnQueueEvent(state.queue, events);
174       });
175 }
176
177 Status<void> DisplaySurface::UnregisterQueue(
178     const std::shared_ptr<ConsumerQueue>& consumer_queue) {
179   ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d",
180            surface_id(), consumer_queue->id());
181   return service()->RemoveEventHandler(consumer_queue->queue_fd());
182 }
183
184 void DisplaySurface::OnQueueEvent(
185     const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) {
186   ALOGE(
187       "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be "
188       "called!!!");
189 }
190
191 std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
192     int32_t queue_id) {
193   ALOGD_IF(TRACE,
194            "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
195            surface_id(), queue_id);
196
197   std::lock_guard<std::mutex> autolock(lock_);
198   auto search = consumer_queues_.find(queue_id);
199   if (search != consumer_queues_.end())
200     return search->second;
201   else
202     return nullptr;
203 }
204
205 std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
206   std::lock_guard<std::mutex> autolock(lock_);
207   std::vector<int32_t> queue_ids;
208   for (const auto& entry : consumer_queues_)
209     queue_ids.push_back(entry.first);
210   return queue_ids;
211 }
212
213 Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
214     Message& /*message*/, const ProducerQueueConfig& config) {
215   ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
216   ALOGD_IF(TRACE,
217            "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
218            "meta_size_bytes=%zu",
219            surface_id(), config.meta_size_bytes);
220
221   std::lock_guard<std::mutex> autolock(lock_);
222   auto producer = ProducerQueue::Create(config, UsagePolicy{});
223   if (!producer) {
224     ALOGE(
225         "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
226         "queue!");
227     return ErrorStatus(ENOMEM);
228   }
229
230   std::shared_ptr<ConsumerQueue> consumer =
231       producer->CreateSilentConsumerQueue();
232   auto status = RegisterQueue(consumer);
233   if (!status) {
234     ALOGE(
235         "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer "
236         "queue: %s",
237         status.GetErrorMessage().c_str());
238     return status.error_status();
239   }
240
241   consumer_queues_[consumer->id()] = std::move(consumer);
242
243   SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
244   return std::move(producer->GetChannelHandle());
245 }
246
247 void ApplicationDisplaySurface::OnQueueEvent(
248     const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
249   ALOGD_IF(TRACE,
250            "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
251            consumer_queue->id(), events);
252
253   std::lock_guard<std::mutex> autolock(lock_);
254
255   // Always give the queue a chance to handle its internal bookkeeping.
256   consumer_queue->HandleQueueEvents();
257
258   // Check for hangup and remove a queue that is no longer needed.
259   if (consumer_queue->hung_up()) {
260     ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue.");
261     UnregisterQueue(consumer_queue);
262     auto search = consumer_queues_.find(consumer_queue->id());
263     if (search != consumer_queues_.end()) {
264       consumer_queues_.erase(search);
265     } else {
266       ALOGE(
267           "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d",
268           consumer_queue->id());
269     }
270     SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
271   }
272 }
273
274 std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const {
275   std::lock_guard<std::mutex> autolock(lock_);
276   std::vector<int32_t> queue_ids;
277   if (direct_queue_)
278     queue_ids.push_back(direct_queue_->id());
279   return queue_ids;
280 }
281
282 Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
283     Message& /*message*/, const ProducerQueueConfig& config) {
284   ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
285   ALOGD_IF(
286       TRACE,
287       "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
288       surface_id(), config.meta_size_bytes);
289
290   std::lock_guard<std::mutex> autolock(lock_);
291   if (!direct_queue_) {
292     // Inject the hw composer usage flag to enable the display to read the
293     // buffers.
294     auto producer = ProducerQueue::Create(
295         config, UsagePolicy{GraphicBuffer::USAGE_HW_COMPOSER, 0, 0, 0});
296     if (!producer) {
297       ALOGE(
298           "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
299           "queue!");
300       return ErrorStatus(ENOMEM);
301     }
302
303     direct_queue_ = producer->CreateConsumerQueue();
304     if (direct_queue_->metadata_size() > 0) {
305       metadata_.reset(new uint8_t[direct_queue_->metadata_size()]);
306     }
307     auto status = RegisterQueue(direct_queue_);
308     if (!status) {
309       ALOGE(
310           "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
311           "queue: %s",
312           status.GetErrorMessage().c_str());
313       return status.error_status();
314     }
315
316     return std::move(producer->GetChannelHandle());
317   } else {
318     return ErrorStatus(EALREADY);
319   }
320 }
321
322 void DirectDisplaySurface::OnQueueEvent(
323     const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
324   ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
325            consumer_queue->id(), events);
326
327   std::lock_guard<std::mutex> autolock(lock_);
328
329   // Always give the queue a chance to handle its internal bookkeeping.
330   consumer_queue->HandleQueueEvents();
331
332   // Check for hangup and remove a queue that is no longer needed.
333   if (consumer_queue->hung_up()) {
334     ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
335     UnregisterQueue(consumer_queue);
336     direct_queue_ = nullptr;
337   }
338 }
339
340 void DirectDisplaySurface::DequeueBuffersLocked() {
341   if (direct_queue_ == nullptr) {
342     ALOGE(
343         "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
344         "initialized.");
345     return;
346   }
347
348   while (true) {
349     LocalHandle acquire_fence;
350     size_t slot;
351     auto buffer_status = direct_queue_->Dequeue(
352         0, &slot, metadata_.get(),
353         direct_queue_->metadata_size(), &acquire_fence);
354     ALOGD_IF(TRACE,
355              "DirectDisplaySurface::DequeueBuffersLocked: Dequeue with metadata_size: %zu",
356              direct_queue_->metadata_size());
357     if (!buffer_status) {
358       ALOGD_IF(
359           TRACE > 1 && buffer_status.error() == ETIMEDOUT,
360           "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
361       ALOGE_IF(buffer_status.error() != ETIMEDOUT,
362                "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
363                "buffer: %s",
364                buffer_status.GetErrorMessage().c_str());
365       return;
366     }
367     auto buffer_consumer = buffer_status.take();
368
369     if (!visible()) {
370       ATRACE_NAME("DropFrameOnInvisibleSurface");
371       ALOGD_IF(TRACE,
372                "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
373                "buffer_id=%d on invisible surface.",
374                buffer_consumer->id());
375       buffer_consumer->Discard();
376       continue;
377     }
378
379     if (acquired_buffers_.IsFull()) {
380       ALOGE(
381           "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
382           "overwriting.");
383       acquired_buffers_.PopBack();
384     }
385
386     acquired_buffers_.Append(
387         AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
388   }
389 }
390
391 AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
392   std::lock_guard<std::mutex> autolock(lock_);
393   DequeueBuffersLocked();
394
395   if (acquired_buffers_.IsEmpty()) {
396     ALOGE(
397         "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
398         "when none are posted.");
399     return AcquiredBuffer();
400   }
401   AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
402   acquired_buffers_.PopFront();
403   ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer_id=%d",
404            buffer.buffer()->id());
405   return buffer;
406 }
407
408 AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
409     AcquiredBuffer* skipped_buffer) {
410   std::lock_guard<std::mutex> autolock(lock_);
411   DequeueBuffersLocked();
412
413   AcquiredBuffer buffer;
414   int frames = 0;
415   // Basic latency stopgap for when the application misses a frame:
416   // If the application recovers on the 2nd or 3rd (etc) frame after
417   // missing, this code will skip frames to catch up by checking if
418   // the next frame is also available.
419   while (!acquired_buffers_.IsEmpty() &&
420          acquired_buffers_.Front().IsAvailable()) {
421     // Capture the skipped buffer into the result parameter.
422     // Note that this API only supports skipping one buffer per vsync.
423     if (frames > 0 && skipped_buffer)
424       *skipped_buffer = std::move(buffer);
425     ++frames;
426     buffer = std::move(acquired_buffers_.Front());
427     acquired_buffers_.PopFront();
428     if (frames == 2)
429       break;
430   }
431   ALOGD_IF(TRACE,
432            "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer_id=%d",
433            buffer.buffer()->id());
434   return buffer;
435 }
436
437 bool DirectDisplaySurface::IsBufferAvailable() {
438   std::lock_guard<std::mutex> autolock(lock_);
439   DequeueBuffersLocked();
440
441   return !acquired_buffers_.IsEmpty() &&
442          acquired_buffers_.Front().IsAvailable();
443 }
444
445 bool DirectDisplaySurface::IsBufferPosted() {
446   std::lock_guard<std::mutex> autolock(lock_);
447   DequeueBuffersLocked();
448
449   return !acquired_buffers_.IsEmpty();
450 }
451
452 Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
453     DisplayService* service, int surface_id, int process_id, int user_id,
454     const display::SurfaceAttributes& attributes) {
455   bool direct = false;
456   auto search = attributes.find(display::SurfaceAttribute::Direct);
457   if (search != attributes.end()) {
458     if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
459                                                      &direct)) {
460       ALOGE(
461           "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
462       return ErrorStatus(EINVAL);
463     }
464   }
465
466   ALOGD_IF(TRACE,
467            "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
468            "direct=%d",
469            surface_id, process_id, user_id, direct);
470
471   if (direct) {
472     const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
473     if (trusted) {
474       return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
475           service, surface_id, process_id, user_id, attributes)}};
476     } else {
477       ALOGE(
478           "DisplaySurface::Create: Direct surfaces may only be created by "
479           "trusted UIDs: user_id=%d",
480           user_id);
481       return ErrorStatus(EPERM);
482     }
483   } else {
484     return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
485         service, surface_id, process_id, user_id, attributes)}};
486   }
487 }
488
489 }  // namespace dvr
490 }  // namespace android