blob: 0d6a732a8e6093cdbad77131f67c7c77bf2b2bad [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,
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),
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080034 process_id_(process_id),
Corey Tabaka2251d822017-04-20 16:04:07 -070035 user_id_(user_id),
36 attributes_(attributes),
37 update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080038
39DisplaySurface::~DisplaySurface() {
40 ALOGD_IF(LOCAL_TRACE,
41 "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
Corey Tabaka2251d822017-04-20 16:04:07 -070042 surface_id(), process_id());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080043}
44
Corey Tabaka2251d822017-04-20 16:04:07 -070045Status<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) {
Corey Tabaka49a706d2017-06-08 14:29:58 -070071 const auto key = attribute.first;
Corey Tabaka2251d822017-04-20 16:04:07 -070072 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
Corey Tabaka49a706d2017-06-08 14:29:58 -070098 // 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.
Corey Tabaka2251d822017-04-20 16:04:07 -0700101 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 {
Corey Tabaka49a706d2017-06-08 14:29:58 -0700107 // 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 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700115
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
129void 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
138void DisplaySurface::ClearUpdate() {
Corey Tabaka89bbefc2017-06-06 16:14:21 -0700139 ALOGD_IF(TRACE > 1, "DisplaySurface::ClearUpdate: surface_id=%d",
140 surface_id());
Corey Tabaka2251d822017-04-20 16:04:07 -0700141 update_flags_ = display::SurfaceUpdateFlags::None;
142}
143
144Status<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
153Status<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
177Status<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
184void 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
191std::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
Corey Tabakacf023722017-07-28 19:46:30 -0700197 std::lock_guard<std::mutex> autolock(lock_);
Corey Tabaka2251d822017-04-20 16:04:07 -0700198 auto search = consumer_queues_.find(queue_id);
199 if (search != consumer_queues_.end())
200 return search->second;
201 else
202 return nullptr;
203}
204
205std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
Corey Tabakacf023722017-07-28 19:46:30 -0700206 std::lock_guard<std::mutex> autolock(lock_);
Corey Tabaka2251d822017-04-20 16:04:07 -0700207 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
213Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700214 Message& /*message*/, const ProducerQueueConfig& config) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700215 ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
216 ALOGD_IF(TRACE,
217 "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
218 "meta_size_bytes=%zu",
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700219 surface_id(), config.meta_size_bytes);
Corey Tabaka2251d822017-04-20 16:04:07 -0700220
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800221 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700222 auto producer = ProducerQueue::Create(config, UsagePolicy{});
Corey Tabaka2251d822017-04-20 16:04:07 -0700223 if (!producer) {
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800224 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700225 "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
247void 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
Corey Tabakae36f1e42017-07-06 15:39:49 -0700253 std::lock_guard<std::mutex> autolock(lock_);
254
Corey Tabaka2251d822017-04-20 16:04:07 -0700255 // 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.
Corey Tabaka2251d822017-04-20 16:04:07 -0700259 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
Corey Tabaka0b485c92017-05-19 12:02:58 -0700274std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const {
Corey Tabakacf023722017-07-28 19:46:30 -0700275 std::lock_guard<std::mutex> autolock(lock_);
Corey Tabaka0b485c92017-05-19 12:02:58 -0700276 std::vector<int32_t> queue_ids;
277 if (direct_queue_)
278 queue_ids.push_back(direct_queue_->id());
279 return queue_ids;
280}
281
Corey Tabaka2251d822017-04-20 16:04:07 -0700282Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700283 Message& /*message*/, const ProducerQueueConfig& config) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700284 ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
285 ALOGD_IF(
286 TRACE,
287 "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700288 surface_id(), config.meta_size_bytes);
Corey Tabaka2251d822017-04-20 16:04:07 -0700289
290 std::lock_guard<std::mutex> autolock(lock_);
291 if (!direct_queue_) {
Corey Tabakaa936f7a2017-05-18 17:28:07 -0700292 // Inject the hw composer usage flag to enable the display to read the
293 // buffers.
294 auto producer = ProducerQueue::Create(
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700295 config, UsagePolicy{GraphicBuffer::USAGE_HW_COMPOSER, 0, 0, 0});
Corey Tabaka2251d822017-04-20 16:04:07 -0700296 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 auto status = RegisterQueue(direct_queue_);
305 if (!status) {
306 ALOGE(
307 "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
308 "queue: %s",
309 status.GetErrorMessage().c_str());
310 return status.error_status();
311 }
312
313 return std::move(producer->GetChannelHandle());
314 } else {
315 return ErrorStatus(EALREADY);
316 }
317}
318
319void DirectDisplaySurface::OnQueueEvent(
320 const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
321 ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
322 consumer_queue->id(), events);
323
Corey Tabakae36f1e42017-07-06 15:39:49 -0700324 std::lock_guard<std::mutex> autolock(lock_);
325
Corey Tabaka2251d822017-04-20 16:04:07 -0700326 // Always give the queue a chance to handle its internal bookkeeping.
327 consumer_queue->HandleQueueEvents();
328
329 // Check for hangup and remove a queue that is no longer needed.
Corey Tabaka2251d822017-04-20 16:04:07 -0700330 if (consumer_queue->hung_up()) {
331 ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
332 UnregisterQueue(consumer_queue);
333 direct_queue_ = nullptr;
334 }
335}
336
337void DirectDisplaySurface::DequeueBuffersLocked() {
338 if (direct_queue_ == nullptr) {
339 ALOGE(
340 "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800341 "initialized.");
342 return;
343 }
344
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800345 while (true) {
346 LocalHandle acquire_fence;
Corey Tabaka2251d822017-04-20 16:04:07 -0700347 size_t slot;
348 auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
349 if (!buffer_status) {
350 ALOGD_IF(
Corey Tabaka89bbefc2017-06-06 16:14:21 -0700351 TRACE > 1 && buffer_status.error() == ETIMEDOUT,
Corey Tabaka2251d822017-04-20 16:04:07 -0700352 "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
353 ALOGE_IF(buffer_status.error() != ETIMEDOUT,
354 "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
355 "buffer: %s",
356 buffer_status.GetErrorMessage().c_str());
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800357 return;
358 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700359 auto buffer_consumer = buffer_status.take();
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800360
Corey Tabaka2251d822017-04-20 16:04:07 -0700361 if (!visible()) {
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800362 ATRACE_NAME("DropFrameOnInvisibleSurface");
363 ALOGD_IF(TRACE,
Corey Tabaka2251d822017-04-20 16:04:07 -0700364 "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
365 "buffer_id=%d on invisible surface.",
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800366 buffer_consumer->id());
367 buffer_consumer->Discard();
368 continue;
369 }
370
371 if (acquired_buffers_.IsFull()) {
372 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700373 "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800374 "overwriting.");
375 acquired_buffers_.PopBack();
376 }
377
378 acquired_buffers_.Append(
Corey Tabaka2251d822017-04-20 16:04:07 -0700379 AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800380 }
381}
382
Corey Tabaka2251d822017-04-20 16:04:07 -0700383AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800384 std::lock_guard<std::mutex> autolock(lock_);
385 DequeueBuffersLocked();
386
387 if (acquired_buffers_.IsEmpty()) {
388 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700389 "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
390 "when none are posted.");
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800391 return AcquiredBuffer();
392 }
393 AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
394 acquired_buffers_.PopFront();
Corey Tabaka0b485c92017-05-19 12:02:58 -0700395 ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer_id=%d",
396 buffer.buffer()->id());
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800397 return buffer;
398}
399
Corey Tabaka2251d822017-04-20 16:04:07 -0700400AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800401 AcquiredBuffer* skipped_buffer) {
402 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800403 DequeueBuffersLocked();
404
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800405 AcquiredBuffer buffer;
406 int frames = 0;
407 // Basic latency stopgap for when the application misses a frame:
408 // If the application recovers on the 2nd or 3rd (etc) frame after
409 // missing, this code will skip frames to catch up by checking if
410 // the next frame is also available.
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800411 while (!acquired_buffers_.IsEmpty() &&
412 acquired_buffers_.Front().IsAvailable()) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800413 // Capture the skipped buffer into the result parameter.
414 // Note that this API only supports skipping one buffer per vsync.
415 if (frames > 0 && skipped_buffer)
416 *skipped_buffer = std::move(buffer);
417 ++frames;
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800418 buffer = std::move(acquired_buffers_.Front());
419 acquired_buffers_.PopFront();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800420 if (frames == 2)
421 break;
422 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700423 ALOGD_IF(TRACE,
Corey Tabaka0b485c92017-05-19 12:02:58 -0700424 "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer_id=%d",
425 buffer.buffer()->id());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800426 return buffer;
427}
428
Corey Tabaka2251d822017-04-20 16:04:07 -0700429bool DirectDisplaySurface::IsBufferAvailable() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800430 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800431 DequeueBuffersLocked();
432
433 return !acquired_buffers_.IsEmpty() &&
434 acquired_buffers_.Front().IsAvailable();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800435}
436
Corey Tabaka2251d822017-04-20 16:04:07 -0700437bool DirectDisplaySurface::IsBufferPosted() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800438 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800439 DequeueBuffersLocked();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800440
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800441 return !acquired_buffers_.IsEmpty();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800442}
443
Corey Tabaka2251d822017-04-20 16:04:07 -0700444Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
445 DisplayService* service, int surface_id, int process_id, int user_id,
446 const display::SurfaceAttributes& attributes) {
447 bool direct = false;
448 auto search = attributes.find(display::SurfaceAttribute::Direct);
449 if (search != attributes.end()) {
450 if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
451 &direct)) {
452 ALOGE(
453 "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
454 return ErrorStatus(EINVAL);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800455 }
456 }
457
Corey Tabaka2251d822017-04-20 16:04:07 -0700458 ALOGD_IF(TRACE,
459 "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
460 "direct=%d",
461 surface_id, process_id, user_id, direct);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800462
Corey Tabaka2251d822017-04-20 16:04:07 -0700463 if (direct) {
464 const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
465 if (trusted) {
466 return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
467 service, surface_id, process_id, user_id, attributes)}};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800468 } else {
Corey Tabaka2251d822017-04-20 16:04:07 -0700469 ALOGE(
470 "DisplaySurface::Create: Direct surfaces may only be created by "
471 "trusted UIDs: user_id=%d",
472 user_id);
473 return ErrorStatus(EPERM);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800474 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700475 } else {
476 return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
477 service, surface_id, process_id, user_id, attributes)}};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800478 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800479}
480
481} // namespace dvr
482} // namespace android