#include "display_manager_service.h" #include #include #include #include #include #include #include using android::dvr::display::DisplayManagerProtocol; using android::pdx::Channel; using android::pdx::LocalChannelHandle; using android::pdx::Message; using android::pdx::default_transport::Endpoint; using android::pdx::ErrorStatus; using android::pdx::rpc::DispatchRemoteMethod; using android::pdx::rpc::IfAnyOf; using android::pdx::rpc::RemoteMethodError; namespace android { namespace dvr { void DisplayManager::SetNotificationsPending(bool pending) { auto status = service_->ModifyChannelEvents(channel_id_, pending ? 0 : POLLIN, pending ? POLLIN : 0); ALOGE_IF(!status, "DisplayManager::SetNotificationPending: Failed to modify channel " "events: %s", status.GetErrorMessage().c_str()); } DisplayManagerService::DisplayManagerService( const std::shared_ptr& display_service) : BASE("DisplayManagerService", Endpoint::Create(DisplayManagerProtocol::kClientPath)), display_service_(display_service) { display_service_->SetDisplayConfigurationUpdateNotifier( std::bind(&DisplayManagerService::OnDisplaySurfaceChange, this)); } std::shared_ptr DisplayManagerService::OnChannelOpen( pdx::Message& message) { const int user_id = message.GetEffectiveUserId(); const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id); // Check if the display_manager_ has a defunct channel. if (display_manager_ && !HasChannelId(display_manager_->channel_id())) { ALOGE("DisplayManagerService::OnChannelOpen: Found defunct channel %d with " "no OnChannelClose, clearing prior display manager.", display_manager_->channel_id()); display_manager_ = nullptr; } // Prevent more than one display manager from registering at a time or // untrusted UIDs from connecting. if (display_manager_ || !trusted) { RemoteMethodError(message, EPERM); return nullptr; } display_manager_ = std::make_shared(this, message.GetChannelId()); return display_manager_; } void DisplayManagerService::OnChannelClose( pdx::Message& /*message*/, const std::shared_ptr& channel) { // Unregister the display manager when the channel closes. if (display_manager_ == channel) display_manager_ = nullptr; } pdx::Status DisplayManagerService::HandleMessage(pdx::Message& message) { ATRACE_NAME("DisplayManagerService::HandleMessage"); auto channel = std::static_pointer_cast(message.GetChannel()); switch (message.GetOp()) { case DisplayManagerProtocol::GetSurfaceState::Opcode: DispatchRemoteMethod( *this, &DisplayManagerService::OnGetSurfaceState, message); return {}; case DisplayManagerProtocol::GetSurfaceQueue::Opcode: DispatchRemoteMethod( *this, &DisplayManagerService::OnGetSurfaceQueue, message); return {}; default: return Service::DefaultHandleMessage(message); } } pdx::Status> DisplayManagerService::OnGetSurfaceState(pdx::Message& /*message*/) { std::vector items; display_service_->ForEachDisplaySurface( SurfaceType::Application, [&items](const std::shared_ptr& surface) mutable { items.push_back({surface->surface_id(), surface->process_id(), surface->user_id(), surface->attributes(), surface->update_flags(), surface->GetQueueIds()}); surface->ClearUpdate(); }); // The fact that we're in the message handler implies that display_manager_ is // not nullptr. No check required, unless this service becomes multi-threaded. display_manager_->SetNotificationsPending(false); return items; } pdx::Status DisplayManagerService::OnGetSurfaceQueue( pdx::Message& /*message*/, int surface_id, int queue_id) { auto surface = display_service_->GetDisplaySurface(surface_id); if (!surface || surface->surface_type() != SurfaceType::Application) return ErrorStatus(EINVAL); auto queue = std::static_pointer_cast(surface)->GetQueue( queue_id); if (!queue) return ErrorStatus(EINVAL); auto status = queue->CreateConsumerQueueHandle(); ALOGE_IF( !status, "DisplayManagerService::OnGetSurfaceQueue: Failed to create consumer " "queue for queue_id=%d: %s", queue->id(), status.GetErrorMessage().c_str()); return status; } void DisplayManagerService::OnDisplaySurfaceChange() { if (display_manager_) display_manager_->SetNotificationsPending(true); } } // namespace dvr } // namespace android