display_surface.cpp revision 2251d822dac2a96aad4184a6fdc2690f0a58af7c
1#include "display_surface.h" 2 3#include <private/android_filesystem_config.h> 4#include <utils/Trace.h> 5 6#include <private/dvr/platform_defines.h> 7#include <private/dvr/trusted_uids.h> 8 9#include "display_service.h" 10#include "hardware_composer.h" 11 12#define LOCAL_TRACE 1 13 14using android::dvr::display::DisplayProtocol; 15using android::pdx::BorrowedChannelHandle; 16using android::pdx::ErrorStatus; 17using android::pdx::LocalChannelHandle; 18using android::pdx::LocalHandle; 19using android::pdx::Message; 20using android::pdx::RemoteChannelHandle; 21using android::pdx::Status; 22using android::pdx::rpc::DispatchRemoteMethod; 23using android::pdx::rpc::IfAnyOf; 24 25namespace android { 26namespace dvr { 27 28DisplaySurface::DisplaySurface(DisplayService* service, 29 SurfaceType surface_type, int surface_id, 30 int process_id, int user_id, 31 const display::SurfaceAttributes& attributes) 32 : service_(service), 33 surface_type_(surface_type), 34 surface_id_(surface_id), 35 process_id_(process_id), 36 user_id_(user_id), 37 attributes_(attributes), 38 update_flags_(display::SurfaceUpdateFlags::NewSurface) {} 39 40DisplaySurface::~DisplaySurface() { 41 ALOGD_IF(LOCAL_TRACE, 42 "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d", 43 surface_id(), process_id()); 44} 45 46Status<void> DisplaySurface::HandleMessage(pdx::Message& message) { 47 switch (message.GetOp()) { 48 case DisplayProtocol::SetAttributes::Opcode: 49 DispatchRemoteMethod<DisplayProtocol::SetAttributes>( 50 *this, &DisplaySurface::OnSetAttributes, message); 51 break; 52 53 case DisplayProtocol::GetSurfaceInfo::Opcode: 54 DispatchRemoteMethod<DisplayProtocol::GetSurfaceInfo>( 55 *this, &DisplaySurface::OnGetSurfaceInfo, message); 56 break; 57 58 case DisplayProtocol::CreateQueue::Opcode: 59 DispatchRemoteMethod<DisplayProtocol::CreateQueue>( 60 *this, &DisplaySurface::OnCreateQueue, message); 61 break; 62 } 63 64 return {}; 65} 66 67Status<void> DisplaySurface::OnSetAttributes( 68 pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) { 69 display::SurfaceUpdateFlags update_flags; 70 71 for (const auto& attribute : attributes) { 72 const auto& key = attribute.first; 73 const auto* variant = &attribute.second; 74 bool invalid_value = false; 75 bool visibility_changed = false; 76 77 // Catch attributes that have significance to the display service. 78 switch (key) { 79 case display::SurfaceAttribute::ZOrder: 80 invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call( 81 variant, [&](const auto& value) { 82 if (z_order_ != value) { 83 visibility_changed = true; 84 z_order_ = value; 85 } 86 }); 87 break; 88 case display::SurfaceAttribute::Visible: 89 invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call( 90 variant, [&](const auto& value) { 91 if (visible_ != value) { 92 visibility_changed = true; 93 visible_ = value; 94 } 95 }); 96 break; 97 } 98 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 // Only update the attribute map with valid values. 106 attributes_[attribute.first] = attribute.second; 107 108 // All attribute changes generate a notification, even if the value 109 // doesn't change. Visibility attributes set a flag only if the value 110 // changes. 111 update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged); 112 if (visibility_changed) 113 update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged); 114 } 115 } 116 117 SurfaceUpdated(update_flags); 118 return {}; 119} 120 121void DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) { 122 ALOGD_IF(TRACE, 123 "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x", 124 surface_id(), update_flags.value()); 125 126 update_flags_.Set(update_flags); 127 service()->SurfaceUpdated(surface_type(), update_flags_); 128} 129 130void DisplaySurface::ClearUpdate() { 131 ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id()); 132 update_flags_ = display::SurfaceUpdateFlags::None; 133} 134 135Status<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 144Status<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 168Status<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 175void 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 182std::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 195std::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 202Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue( 203 Message& /*message*/, size_t meta_size_bytes) { 204 ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue"); 205 ALOGD_IF(TRACE, 206 "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, " 207 "meta_size_bytes=%zu", 208 surface_id(), meta_size_bytes); 209 210 std::lock_guard<std::mutex> autolock(lock_); 211 auto producer = ProducerQueue::Create(meta_size_bytes); 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 236void 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 262Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue( 263 Message& /*message*/, size_t meta_size_bytes) { 264 ATRACE_NAME("DirectDisplaySurface::OnCreateQueue"); 265 ALOGD_IF( 266 TRACE, 267 "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu", 268 surface_id(), meta_size_bytes); 269 270 std::lock_guard<std::mutex> autolock(lock_); 271 if (!direct_queue_) { 272 auto producer = ProducerQueue::Create(meta_size_bytes); 273 if (!producer) { 274 ALOGE( 275 "DirectDisplaySurface::OnCreateQueue: Failed to create producer " 276 "queue!"); 277 return ErrorStatus(ENOMEM); 278 } 279 280 direct_queue_ = producer->CreateConsumerQueue(); 281 auto status = RegisterQueue(direct_queue_); 282 if (!status) { 283 ALOGE( 284 "DirectDisplaySurface::OnCreateQueue: Failed to register consumer " 285 "queue: %s", 286 status.GetErrorMessage().c_str()); 287 return status.error_status(); 288 } 289 290 return std::move(producer->GetChannelHandle()); 291 } else { 292 return ErrorStatus(EALREADY); 293 } 294} 295 296void DirectDisplaySurface::OnQueueEvent( 297 const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) { 298 ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x", 299 consumer_queue->id(), events); 300 301 // Always give the queue a chance to handle its internal bookkeeping. 302 consumer_queue->HandleQueueEvents(); 303 304 // Check for hangup and remove a queue that is no longer needed. 305 std::lock_guard<std::mutex> autolock(lock_); 306 if (consumer_queue->hung_up()) { 307 ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue."); 308 UnregisterQueue(consumer_queue); 309 direct_queue_ = nullptr; 310 } 311} 312 313void DirectDisplaySurface::DequeueBuffersLocked() { 314 if (direct_queue_ == nullptr) { 315 ALOGE( 316 "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not " 317 "initialized."); 318 return; 319 } 320 321 while (true) { 322 LocalHandle acquire_fence; 323 size_t slot; 324 auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence); 325 if (!buffer_status) { 326 ALOGD_IF( 327 TRACE && buffer_status.error() == ETIMEDOUT, 328 "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued."); 329 ALOGE_IF(buffer_status.error() != ETIMEDOUT, 330 "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue " 331 "buffer: %s", 332 buffer_status.GetErrorMessage().c_str()); 333 return; 334 } 335 auto buffer_consumer = buffer_status.take(); 336 337 if (!visible()) { 338 ATRACE_NAME("DropFrameOnInvisibleSurface"); 339 ALOGD_IF(TRACE, 340 "DirectDisplaySurface::DequeueBuffersLocked: Discarding " 341 "buffer_id=%d on invisible surface.", 342 buffer_consumer->id()); 343 buffer_consumer->Discard(); 344 continue; 345 } 346 347 if (acquired_buffers_.IsFull()) { 348 ALOGE( 349 "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, " 350 "overwriting."); 351 acquired_buffers_.PopBack(); 352 } 353 354 acquired_buffers_.Append( 355 AcquiredBuffer(buffer_consumer, std::move(acquire_fence))); 356 } 357} 358 359AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() { 360 std::lock_guard<std::mutex> autolock(lock_); 361 DequeueBuffersLocked(); 362 363 if (acquired_buffers_.IsEmpty()) { 364 ALOGE( 365 "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer " 366 "when none are posted."); 367 return AcquiredBuffer(); 368 } 369 AcquiredBuffer buffer = std::move(acquired_buffers_.Front()); 370 acquired_buffers_.PopFront(); 371 ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p", 372 buffer.buffer().get()); 373 return buffer; 374} 375 376AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer( 377 AcquiredBuffer* skipped_buffer) { 378 std::lock_guard<std::mutex> autolock(lock_); 379 DequeueBuffersLocked(); 380 381 AcquiredBuffer buffer; 382 int frames = 0; 383 // Basic latency stopgap for when the application misses a frame: 384 // If the application recovers on the 2nd or 3rd (etc) frame after 385 // missing, this code will skip frames to catch up by checking if 386 // the next frame is also available. 387 while (!acquired_buffers_.IsEmpty() && 388 acquired_buffers_.Front().IsAvailable()) { 389 // Capture the skipped buffer into the result parameter. 390 // Note that this API only supports skipping one buffer per vsync. 391 if (frames > 0 && skipped_buffer) 392 *skipped_buffer = std::move(buffer); 393 ++frames; 394 buffer = std::move(acquired_buffers_.Front()); 395 acquired_buffers_.PopFront(); 396 if (frames == 2) 397 break; 398 } 399 ALOGD_IF(TRACE, 400 "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p", 401 buffer.buffer().get()); 402 return buffer; 403} 404 405bool DirectDisplaySurface::IsBufferAvailable() { 406 std::lock_guard<std::mutex> autolock(lock_); 407 DequeueBuffersLocked(); 408 409 return !acquired_buffers_.IsEmpty() && 410 acquired_buffers_.Front().IsAvailable(); 411} 412 413bool DirectDisplaySurface::IsBufferPosted() { 414 std::lock_guard<std::mutex> autolock(lock_); 415 DequeueBuffersLocked(); 416 417 return !acquired_buffers_.IsEmpty(); 418} 419 420Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create( 421 DisplayService* service, int surface_id, int process_id, int user_id, 422 const display::SurfaceAttributes& attributes) { 423 bool direct = false; 424 auto search = attributes.find(display::SurfaceAttribute::Direct); 425 if (search != attributes.end()) { 426 if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second, 427 &direct)) { 428 ALOGE( 429 "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!"); 430 return ErrorStatus(EINVAL); 431 } 432 } 433 434 ALOGD_IF(TRACE, 435 "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d " 436 "direct=%d", 437 surface_id, process_id, user_id, direct); 438 439 if (direct) { 440 const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id); 441 if (trusted) { 442 return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface( 443 service, surface_id, process_id, user_id, attributes)}}; 444 } else { 445 ALOGE( 446 "DisplaySurface::Create: Direct surfaces may only be created by " 447 "trusted UIDs: user_id=%d", 448 user_id); 449 return ErrorStatus(EPERM); 450 } 451 } else { 452 return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface( 453 service, surface_id, process_id, user_id, attributes)}}; 454 } 455} 456 457} // namespace dvr 458} // namespace android 459