blob: 685378133e212a958679906e2c17b2d198ae6dd5 [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "display_surface.h"
2
Corey Tabaka2251d822017-04-20 16:04:07 -07003#include <private/android_filesystem_config.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08004#include <utils/Trace.h>
5
Corey Tabaka2251d822017-04-20 16:04:07 -07006#include <private/dvr/trusted_uids.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08007
8#include "display_service.h"
9#include "hardware_composer.h"
10
11#define LOCAL_TRACE 1
12
Corey Tabaka2251d822017-04-20 16:04:07 -070013using android::dvr::display::DisplayProtocol;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080014using android::pdx::BorrowedChannelHandle;
Corey Tabaka2251d822017-04-20 16:04:07 -070015using android::pdx::ErrorStatus;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080016using android::pdx::LocalChannelHandle;
Corey Tabaka2251d822017-04-20 16:04:07 -070017using android::pdx::LocalHandle;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080018using 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
Corey Tabaka2251d822017-04-20 16:04:07 -070027DisplaySurface::DisplaySurface(DisplayService* service,
28 SurfaceType surface_type, int surface_id,
Corey Tabaka00d9bb32017-08-16 19:59:48 -070029 int process_id, int user_id)
Corey Tabaka2251d822017-04-20 16:04:07 -070030 : service_(service),
31 surface_type_(surface_type),
32 surface_id_(surface_id),
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080033 process_id_(process_id),
Corey Tabaka2251d822017-04-20 16:04:07 -070034 user_id_(user_id),
Corey Tabaka2251d822017-04-20 16:04:07 -070035 update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080036
37DisplaySurface::~DisplaySurface() {
38 ALOGD_IF(LOCAL_TRACE,
39 "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
Corey Tabaka2251d822017-04-20 16:04:07 -070040 surface_id(), process_id());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080041}
42
Corey Tabaka2251d822017-04-20 16:04:07 -070043Status<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
64Status<void> DisplaySurface::OnSetAttributes(
65 pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) {
66 display::SurfaceUpdateFlags update_flags;
67
68 for (const auto& attribute : attributes) {
Corey Tabaka49a706d2017-06-08 14:29:58 -070069 const auto key = attribute.first;
Corey Tabaka2251d822017-04-20 16:04:07 -070070 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
Corey Tabaka49a706d2017-06-08 14:29:58 -070096 // 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.
Corey Tabaka2251d822017-04-20 16:04:07 -070099 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 {
Corey Tabaka49a706d2017-06-08 14:29:58 -0700105 // 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 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700113
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
127void 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
136void DisplaySurface::ClearUpdate() {
Corey Tabaka89bbefc2017-06-06 16:14:21 -0700137 ALOGD_IF(TRACE > 1, "DisplaySurface::ClearUpdate: surface_id=%d",
138 surface_id());
Corey Tabaka2251d822017-04-20 16:04:07 -0700139 update_flags_ = display::SurfaceUpdateFlags::None;
140}
141
142Status<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
151Status<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
175Status<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
182void 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
189std::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
Corey Tabakacf023722017-07-28 19:46:30 -0700195 std::lock_guard<std::mutex> autolock(lock_);
Corey Tabaka2251d822017-04-20 16:04:07 -0700196 auto search = consumer_queues_.find(queue_id);
197 if (search != consumer_queues_.end())
198 return search->second;
199 else
200 return nullptr;
201}
202
203std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
Corey Tabakacf023722017-07-28 19:46:30 -0700204 std::lock_guard<std::mutex> autolock(lock_);
Corey Tabaka2251d822017-04-20 16:04:07 -0700205 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
211Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700212 Message& /*message*/, const ProducerQueueConfig& config) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700213 ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
214 ALOGD_IF(TRACE,
215 "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
216 "meta_size_bytes=%zu",
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700217 surface_id(), config.meta_size_bytes);
Corey Tabaka2251d822017-04-20 16:04:07 -0700218
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800219 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700220 auto producer = ProducerQueue::Create(config, UsagePolicy{});
Corey Tabaka2251d822017-04-20 16:04:07 -0700221 if (!producer) {
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800222 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700223 "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
245void 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
Corey Tabakae36f1e42017-07-06 15:39:49 -0700251 std::lock_guard<std::mutex> autolock(lock_);
252
Corey Tabaka2251d822017-04-20 16:04:07 -0700253 // 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.
Corey Tabaka2251d822017-04-20 16:04:07 -0700257 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
Corey Tabaka0b485c92017-05-19 12:02:58 -0700272std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const {
Corey Tabakacf023722017-07-28 19:46:30 -0700273 std::lock_guard<std::mutex> autolock(lock_);
Corey Tabaka0b485c92017-05-19 12:02:58 -0700274 std::vector<int32_t> queue_ids;
275 if (direct_queue_)
276 queue_ids.push_back(direct_queue_->id());
277 return queue_ids;
278}
279
Corey Tabaka2251d822017-04-20 16:04:07 -0700280Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700281 Message& /*message*/, const ProducerQueueConfig& config) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700282 ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
283 ALOGD_IF(
284 TRACE,
285 "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700286 surface_id(), config.meta_size_bytes);
Corey Tabaka2251d822017-04-20 16:04:07 -0700287
288 std::lock_guard<std::mutex> autolock(lock_);
289 if (!direct_queue_) {
Corey Tabakaa936f7a2017-05-18 17:28:07 -0700290 // Inject the hw composer usage flag to enable the display to read the
291 // buffers.
292 auto producer = ProducerQueue::Create(
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700293 config, UsagePolicy{GraphicBuffer::USAGE_HW_COMPOSER, 0, 0, 0});
Corey Tabaka2251d822017-04-20 16:04:07 -0700294 if (!producer) {
295 ALOGE(
296 "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
297 "queue!");
298 return ErrorStatus(ENOMEM);
299 }
300
301 direct_queue_ = producer->CreateConsumerQueue();
rongliuf60f3072017-07-28 15:22:17 -0700302 if (direct_queue_->metadata_size() > 0) {
303 metadata_.reset(new uint8_t[direct_queue_->metadata_size()]);
304 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700305 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
320void 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
Corey Tabakae36f1e42017-07-06 15:39:49 -0700325 std::lock_guard<std::mutex> autolock(lock_);
326
Corey Tabaka2251d822017-04-20 16:04:07 -0700327 // 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.
Corey Tabaka2251d822017-04-20 16:04:07 -0700331 if (consumer_queue->hung_up()) {
332 ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
333 UnregisterQueue(consumer_queue);
334 direct_queue_ = nullptr;
335 }
336}
337
338void DirectDisplaySurface::DequeueBuffersLocked() {
339 if (direct_queue_ == nullptr) {
340 ALOGE(
341 "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800342 "initialized.");
343 return;
344 }
345
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800346 while (true) {
347 LocalHandle acquire_fence;
Corey Tabaka2251d822017-04-20 16:04:07 -0700348 size_t slot;
rongliuf60f3072017-07-28 15:22:17 -0700349 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());
Corey Tabaka2251d822017-04-20 16:04:07 -0700355 if (!buffer_status) {
356 ALOGD_IF(
Corey Tabaka89bbefc2017-06-06 16:14:21 -0700357 TRACE > 1 && buffer_status.error() == ETIMEDOUT,
Corey Tabaka2251d822017-04-20 16:04:07 -0700358 "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());
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800363 return;
364 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700365 auto buffer_consumer = buffer_status.take();
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800366
Corey Tabaka2251d822017-04-20 16:04:07 -0700367 if (!visible()) {
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800368 ATRACE_NAME("DropFrameOnInvisibleSurface");
369 ALOGD_IF(TRACE,
Corey Tabaka2251d822017-04-20 16:04:07 -0700370 "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
371 "buffer_id=%d on invisible surface.",
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800372 buffer_consumer->id());
373 buffer_consumer->Discard();
374 continue;
375 }
376
377 if (acquired_buffers_.IsFull()) {
378 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700379 "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800380 "overwriting.");
381 acquired_buffers_.PopBack();
382 }
383
384 acquired_buffers_.Append(
Corey Tabaka2251d822017-04-20 16:04:07 -0700385 AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800386 }
387}
388
Corey Tabaka2251d822017-04-20 16:04:07 -0700389AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800390 std::lock_guard<std::mutex> autolock(lock_);
391 DequeueBuffersLocked();
392
393 if (acquired_buffers_.IsEmpty()) {
394 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700395 "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
396 "when none are posted.");
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800397 return AcquiredBuffer();
398 }
399 AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
400 acquired_buffers_.PopFront();
Corey Tabaka0b485c92017-05-19 12:02:58 -0700401 ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer_id=%d",
402 buffer.buffer()->id());
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800403 return buffer;
404}
405
Corey Tabaka2251d822017-04-20 16:04:07 -0700406AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800407 AcquiredBuffer* skipped_buffer) {
408 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800409 DequeueBuffersLocked();
410
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800411 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.
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800417 while (!acquired_buffers_.IsEmpty() &&
418 acquired_buffers_.Front().IsAvailable()) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800419 // 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;
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800424 buffer = std::move(acquired_buffers_.Front());
425 acquired_buffers_.PopFront();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800426 if (frames == 2)
427 break;
428 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700429 ALOGD_IF(TRACE,
Corey Tabaka0b485c92017-05-19 12:02:58 -0700430 "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer_id=%d",
431 buffer.buffer()->id());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800432 return buffer;
433}
434
Corey Tabaka2251d822017-04-20 16:04:07 -0700435bool DirectDisplaySurface::IsBufferAvailable() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800436 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800437 DequeueBuffersLocked();
438
439 return !acquired_buffers_.IsEmpty() &&
440 acquired_buffers_.Front().IsAvailable();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800441}
442
Corey Tabaka2251d822017-04-20 16:04:07 -0700443bool DirectDisplaySurface::IsBufferPosted() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800444 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800445 DequeueBuffersLocked();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800446
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800447 return !acquired_buffers_.IsEmpty();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800448}
449
Corey Tabaka2251d822017-04-20 16:04:07 -0700450Status<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);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800461 }
462 }
463
Corey Tabaka2251d822017-04-20 16:04:07 -0700464 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);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800468
Corey Tabaka2251d822017-04-20 16:04:07 -0700469 if (direct) {
470 const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
471 if (trusted) {
Corey Tabaka00d9bb32017-08-16 19:59:48 -0700472 return {std::shared_ptr<DisplaySurface>{
473 new DirectDisplaySurface(service, surface_id, process_id, user_id)}};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800474 } else {
Corey Tabaka2251d822017-04-20 16:04:07 -0700475 ALOGE(
476 "DisplaySurface::Create: Direct surfaces may only be created by "
477 "trusted UIDs: user_id=%d",
478 user_id);
479 return ErrorStatus(EPERM);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800480 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700481 } else {
482 return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
Corey Tabaka00d9bb32017-08-16 19:59:48 -0700483 service, surface_id, process_id, user_id)}};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800484 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800485}
486
487} // namespace dvr
488} // namespace android