OSDN Git Service

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