OSDN Git Service

Disable skip Validate on client composition
[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     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 > 1, "DisplaySurface::ClearUpdate: surface_id=%d",
131            surface_id());
132   update_flags_ = display::SurfaceUpdateFlags::None;
133 }
134
135 Status<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
144 Status<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
168 Status<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
175 void 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
182 std::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
195 std::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
202 Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
203     Message& /*message*/, const ProducerQueueConfig& config) {
204   ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
205   ALOGD_IF(TRACE,
206            "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
207            "meta_size_bytes=%zu",
208            surface_id(), config.meta_size_bytes);
209
210   std::lock_guard<std::mutex> autolock(lock_);
211   auto producer = ProducerQueue::Create(config, UsagePolicy{});
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
236 void 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
262 std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const {
263   std::vector<int32_t> queue_ids;
264   if (direct_queue_)
265     queue_ids.push_back(direct_queue_->id());
266   return queue_ids;
267 }
268
269 Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
270     Message& /*message*/, const ProducerQueueConfig& config) {
271   ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
272   ALOGD_IF(
273       TRACE,
274       "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
275       surface_id(), config.meta_size_bytes);
276
277   std::lock_guard<std::mutex> autolock(lock_);
278   if (!direct_queue_) {
279     // Inject the hw composer usage flag to enable the display to read the
280     // buffers.
281     auto producer = ProducerQueue::Create(
282         config, UsagePolicy{GraphicBuffer::USAGE_HW_COMPOSER, 0, 0, 0});
283     if (!producer) {
284       ALOGE(
285           "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
286           "queue!");
287       return ErrorStatus(ENOMEM);
288     }
289
290     direct_queue_ = producer->CreateConsumerQueue();
291     auto status = RegisterQueue(direct_queue_);
292     if (!status) {
293       ALOGE(
294           "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
295           "queue: %s",
296           status.GetErrorMessage().c_str());
297       return status.error_status();
298     }
299
300     return std::move(producer->GetChannelHandle());
301   } else {
302     return ErrorStatus(EALREADY);
303   }
304 }
305
306 void DirectDisplaySurface::OnQueueEvent(
307     const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
308   ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
309            consumer_queue->id(), events);
310
311   // Always give the queue a chance to handle its internal bookkeeping.
312   consumer_queue->HandleQueueEvents();
313
314   // Check for hangup and remove a queue that is no longer needed.
315   std::lock_guard<std::mutex> autolock(lock_);
316   if (consumer_queue->hung_up()) {
317     ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
318     UnregisterQueue(consumer_queue);
319     direct_queue_ = nullptr;
320   }
321 }
322
323 void DirectDisplaySurface::DequeueBuffersLocked() {
324   if (direct_queue_ == nullptr) {
325     ALOGE(
326         "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
327         "initialized.");
328     return;
329   }
330
331   while (true) {
332     LocalHandle acquire_fence;
333     size_t slot;
334     auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
335     if (!buffer_status) {
336       ALOGD_IF(
337           TRACE > 1 && buffer_status.error() == ETIMEDOUT,
338           "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
339       ALOGE_IF(buffer_status.error() != ETIMEDOUT,
340                "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
341                "buffer: %s",
342                buffer_status.GetErrorMessage().c_str());
343       return;
344     }
345     auto buffer_consumer = buffer_status.take();
346
347     if (!visible()) {
348       ATRACE_NAME("DropFrameOnInvisibleSurface");
349       ALOGD_IF(TRACE,
350                "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
351                "buffer_id=%d on invisible surface.",
352                buffer_consumer->id());
353       buffer_consumer->Discard();
354       continue;
355     }
356
357     if (acquired_buffers_.IsFull()) {
358       ALOGE(
359           "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
360           "overwriting.");
361       acquired_buffers_.PopBack();
362     }
363
364     acquired_buffers_.Append(
365         AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
366   }
367 }
368
369 AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
370   std::lock_guard<std::mutex> autolock(lock_);
371   DequeueBuffersLocked();
372
373   if (acquired_buffers_.IsEmpty()) {
374     ALOGE(
375         "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
376         "when none are posted.");
377     return AcquiredBuffer();
378   }
379   AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
380   acquired_buffers_.PopFront();
381   ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer_id=%d",
382            buffer.buffer()->id());
383   return buffer;
384 }
385
386 AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
387     AcquiredBuffer* skipped_buffer) {
388   std::lock_guard<std::mutex> autolock(lock_);
389   DequeueBuffersLocked();
390
391   AcquiredBuffer buffer;
392   int frames = 0;
393   // Basic latency stopgap for when the application misses a frame:
394   // If the application recovers on the 2nd or 3rd (etc) frame after
395   // missing, this code will skip frames to catch up by checking if
396   // the next frame is also available.
397   while (!acquired_buffers_.IsEmpty() &&
398          acquired_buffers_.Front().IsAvailable()) {
399     // Capture the skipped buffer into the result parameter.
400     // Note that this API only supports skipping one buffer per vsync.
401     if (frames > 0 && skipped_buffer)
402       *skipped_buffer = std::move(buffer);
403     ++frames;
404     buffer = std::move(acquired_buffers_.Front());
405     acquired_buffers_.PopFront();
406     if (frames == 2)
407       break;
408   }
409   ALOGD_IF(TRACE,
410            "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer_id=%d",
411            buffer.buffer()->id());
412   return buffer;
413 }
414
415 bool DirectDisplaySurface::IsBufferAvailable() {
416   std::lock_guard<std::mutex> autolock(lock_);
417   DequeueBuffersLocked();
418
419   return !acquired_buffers_.IsEmpty() &&
420          acquired_buffers_.Front().IsAvailable();
421 }
422
423 bool DirectDisplaySurface::IsBufferPosted() {
424   std::lock_guard<std::mutex> autolock(lock_);
425   DequeueBuffersLocked();
426
427   return !acquired_buffers_.IsEmpty();
428 }
429
430 Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
431     DisplayService* service, int surface_id, int process_id, int user_id,
432     const display::SurfaceAttributes& attributes) {
433   bool direct = false;
434   auto search = attributes.find(display::SurfaceAttribute::Direct);
435   if (search != attributes.end()) {
436     if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
437                                                      &direct)) {
438       ALOGE(
439           "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
440       return ErrorStatus(EINVAL);
441     }
442   }
443
444   ALOGD_IF(TRACE,
445            "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
446            "direct=%d",
447            surface_id, process_id, user_id, direct);
448
449   if (direct) {
450     const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
451     if (trusted) {
452       return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
453           service, surface_id, process_id, user_id, attributes)}};
454     } else {
455       ALOGE(
456           "DisplaySurface::Create: Direct surfaces may only be created by "
457           "trusted UIDs: user_id=%d",
458           user_id);
459       return ErrorStatus(EPERM);
460     }
461   } else {
462     return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
463         service, surface_id, process_id, user_id, attributes)}};
464   }
465 }
466
467 }  // namespace dvr
468 }  // namespace android