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, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id()); 131 update_flags_ = display::SurfaceUpdateFlags::None; 132 } 133 134 Status<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo( 135 Message& /*message*/) { 136 ALOGD_IF( 137 TRACE, 138 "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d", 139 surface_id(), visible(), z_order()); 140 return {{surface_id(), visible(), z_order()}}; 141 } 142 143 Status<void> DisplaySurface::RegisterQueue( 144 const std::shared_ptr<ConsumerQueue>& consumer_queue) { 145 ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d", 146 surface_id(), consumer_queue->id()); 147 // Capture references for the lambda to work around apparent clang bug. 148 // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when 149 // capturing self and consumer_queue by copy in the following case: 150 // auto self = Self(); 151 // [self, consumer_queue](int events) { 152 // self->OnQueueEvent(consuemr_queue, events); } 153 // 154 struct State { 155 std::shared_ptr<DisplaySurface> surface; 156 std::shared_ptr<ConsumerQueue> queue; 157 }; 158 State state{Self(), consumer_queue}; 159 160 return service()->AddEventHandler( 161 consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET, 162 [state](int events) { 163 state.surface->OnQueueEvent(state.queue, events); 164 }); 165 } 166 167 Status<void> DisplaySurface::UnregisterQueue( 168 const std::shared_ptr<ConsumerQueue>& consumer_queue) { 169 ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d", 170 surface_id(), consumer_queue->id()); 171 return service()->RemoveEventHandler(consumer_queue->queue_fd()); 172 } 173 174 void DisplaySurface::OnQueueEvent( 175 const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) { 176 ALOGE( 177 "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be " 178 "called!!!"); 179 } 180 181 std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue( 182 int32_t queue_id) { 183 ALOGD_IF(TRACE, 184 "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d", 185 surface_id(), queue_id); 186 187 auto search = consumer_queues_.find(queue_id); 188 if (search != consumer_queues_.end()) 189 return search->second; 190 else 191 return nullptr; 192 } 193 194 std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const { 195 std::vector<int32_t> queue_ids; 196 for (const auto& entry : consumer_queues_) 197 queue_ids.push_back(entry.first); 198 return queue_ids; 199 } 200 201 Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue( 202 Message& /*message*/, size_t meta_size_bytes) { 203 ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue"); 204 ALOGD_IF(TRACE, 205 "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, " 206 "meta_size_bytes=%zu", 207 surface_id(), meta_size_bytes); 208 209 std::lock_guard<std::mutex> autolock(lock_); 210 auto producer = ProducerQueue::Create(meta_size_bytes); 211 if (!producer) { 212 ALOGE( 213 "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer " 214 "queue!"); 215 return ErrorStatus(ENOMEM); 216 } 217 218 std::shared_ptr<ConsumerQueue> consumer = 219 producer->CreateSilentConsumerQueue(); 220 auto status = RegisterQueue(consumer); 221 if (!status) { 222 ALOGE( 223 "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer " 224 "queue: %s", 225 status.GetErrorMessage().c_str()); 226 return status.error_status(); 227 } 228 229 consumer_queues_[consumer->id()] = std::move(consumer); 230 231 SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged); 232 return std::move(producer->GetChannelHandle()); 233 } 234 235 void ApplicationDisplaySurface::OnQueueEvent( 236 const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) { 237 ALOGD_IF(TRACE, 238 "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x", 239 consumer_queue->id(), events); 240 241 // Always give the queue a chance to handle its internal bookkeeping. 242 consumer_queue->HandleQueueEvents(); 243 244 // Check for hangup and remove a queue that is no longer needed. 245 std::lock_guard<std::mutex> autolock(lock_); 246 if (consumer_queue->hung_up()) { 247 ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue."); 248 UnregisterQueue(consumer_queue); 249 auto search = consumer_queues_.find(consumer_queue->id()); 250 if (search != consumer_queues_.end()) { 251 consumer_queues_.erase(search); 252 } else { 253 ALOGE( 254 "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d", 255 consumer_queue->id()); 256 } 257 SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged); 258 } 259 } 260 261 Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue( 262 Message& /*message*/, size_t meta_size_bytes) { 263 ATRACE_NAME("DirectDisplaySurface::OnCreateQueue"); 264 ALOGD_IF( 265 TRACE, 266 "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu", 267 surface_id(), meta_size_bytes); 268 269 std::lock_guard<std::mutex> autolock(lock_); 270 if (!direct_queue_) { 271 auto producer = ProducerQueue::Create(meta_size_bytes); 272 if (!producer) { 273 ALOGE( 274 "DirectDisplaySurface::OnCreateQueue: Failed to create producer " 275 "queue!"); 276 return ErrorStatus(ENOMEM); 277 } 278 279 direct_queue_ = producer->CreateConsumerQueue(); 280 auto status = RegisterQueue(direct_queue_); 281 if (!status) { 282 ALOGE( 283 "DirectDisplaySurface::OnCreateQueue: Failed to register consumer " 284 "queue: %s", 285 status.GetErrorMessage().c_str()); 286 return status.error_status(); 287 } 288 289 return std::move(producer->GetChannelHandle()); 290 } else { 291 return ErrorStatus(EALREADY); 292 } 293 } 294 295 void DirectDisplaySurface::OnQueueEvent( 296 const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) { 297 ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x", 298 consumer_queue->id(), events); 299 300 // Always give the queue a chance to handle its internal bookkeeping. 301 consumer_queue->HandleQueueEvents(); 302 303 // Check for hangup and remove a queue that is no longer needed. 304 std::lock_guard<std::mutex> autolock(lock_); 305 if (consumer_queue->hung_up()) { 306 ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue."); 307 UnregisterQueue(consumer_queue); 308 direct_queue_ = nullptr; 309 } 310 } 311 312 void DirectDisplaySurface::DequeueBuffersLocked() { 313 if (direct_queue_ == nullptr) { 314 ALOGE( 315 "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not " 316 "initialized."); 317 return; 318 } 319 320 while (true) { 321 LocalHandle acquire_fence; 322 size_t slot; 323 auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence); 324 if (!buffer_status) { 325 ALOGD_IF( 326 TRACE && buffer_status.error() == ETIMEDOUT, 327 "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued."); 328 ALOGE_IF(buffer_status.error() != ETIMEDOUT, 329 "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue " 330 "buffer: %s", 331 buffer_status.GetErrorMessage().c_str()); 332 return; 333 } 334 auto buffer_consumer = buffer_status.take(); 335 336 if (!visible()) { 337 ATRACE_NAME("DropFrameOnInvisibleSurface"); 338 ALOGD_IF(TRACE, 339 "DirectDisplaySurface::DequeueBuffersLocked: Discarding " 340 "buffer_id=%d on invisible surface.", 341 buffer_consumer->id()); 342 buffer_consumer->Discard(); 343 continue; 344 } 345 346 if (acquired_buffers_.IsFull()) { 347 ALOGE( 348 "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, " 349 "overwriting."); 350 acquired_buffers_.PopBack(); 351 } 352 353 acquired_buffers_.Append( 354 AcquiredBuffer(buffer_consumer, std::move(acquire_fence))); 355 } 356 } 357 358 AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() { 359 std::lock_guard<std::mutex> autolock(lock_); 360 DequeueBuffersLocked(); 361 362 if (acquired_buffers_.IsEmpty()) { 363 ALOGE( 364 "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer " 365 "when none are posted."); 366 return AcquiredBuffer(); 367 } 368 AcquiredBuffer buffer = std::move(acquired_buffers_.Front()); 369 acquired_buffers_.PopFront(); 370 ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p", 371 buffer.buffer().get()); 372 return buffer; 373 } 374 375 AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer( 376 AcquiredBuffer* skipped_buffer) { 377 std::lock_guard<std::mutex> autolock(lock_); 378 DequeueBuffersLocked(); 379 380 AcquiredBuffer buffer; 381 int frames = 0; 382 // Basic latency stopgap for when the application misses a frame: 383 // If the application recovers on the 2nd or 3rd (etc) frame after 384 // missing, this code will skip frames to catch up by checking if 385 // the next frame is also available. 386 while (!acquired_buffers_.IsEmpty() && 387 acquired_buffers_.Front().IsAvailable()) { 388 // Capture the skipped buffer into the result parameter. 389 // Note that this API only supports skipping one buffer per vsync. 390 if (frames > 0 && skipped_buffer) 391 *skipped_buffer = std::move(buffer); 392 ++frames; 393 buffer = std::move(acquired_buffers_.Front()); 394 acquired_buffers_.PopFront(); 395 if (frames == 2) 396 break; 397 } 398 ALOGD_IF(TRACE, 399 "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p", 400 buffer.buffer().get()); 401 return buffer; 402 } 403 404 bool DirectDisplaySurface::IsBufferAvailable() { 405 std::lock_guard<std::mutex> autolock(lock_); 406 DequeueBuffersLocked(); 407 408 return !acquired_buffers_.IsEmpty() && 409 acquired_buffers_.Front().IsAvailable(); 410 } 411 412 bool DirectDisplaySurface::IsBufferPosted() { 413 std::lock_guard<std::mutex> autolock(lock_); 414 DequeueBuffersLocked(); 415 416 return !acquired_buffers_.IsEmpty(); 417 } 418 419 Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create( 420 DisplayService* service, int surface_id, int process_id, int user_id, 421 const display::SurfaceAttributes& attributes) { 422 bool direct = false; 423 auto search = attributes.find(display::SurfaceAttribute::Direct); 424 if (search != attributes.end()) { 425 if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second, 426 &direct)) { 427 ALOGE( 428 "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!"); 429 return ErrorStatus(EINVAL); 430 } 431 } 432 433 ALOGD_IF(TRACE, 434 "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d " 435 "direct=%d", 436 surface_id, process_id, user_id, direct); 437 438 if (direct) { 439 const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id); 440 if (trusted) { 441 return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface( 442 service, surface_id, process_id, user_id, attributes)}}; 443 } else { 444 ALOGE( 445 "DisplaySurface::Create: Direct surfaces may only be created by " 446 "trusted UIDs: user_id=%d", 447 user_id); 448 return ErrorStatus(EPERM); 449 } 450 } else { 451 return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface( 452 service, surface_id, process_id, user_id, attributes)}}; 453 } 454 } 455 456 } // namespace dvr 457 } // namespace android 458