You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
5.0 KiB
143 lines
5.0 KiB
#include "display_manager_service.h"
|
|
|
|
#include <pdx/channel_handle.h>
|
|
#include <pdx/default_transport/service_endpoint.h>
|
|
#include <private/android_filesystem_config.h>
|
|
#include <private/dvr/display_protocol.h>
|
|
#include <private/dvr/trusted_uids.h>
|
|
#include <sys/poll.h>
|
|
|
|
#include <array>
|
|
|
|
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<DisplayService>& display_service)
|
|
: BASE("DisplayManagerService",
|
|
Endpoint::Create(DisplayManagerProtocol::kClientPath)),
|
|
display_service_(display_service) {
|
|
display_service_->SetDisplayConfigurationUpdateNotifier(
|
|
std::bind(&DisplayManagerService::OnDisplaySurfaceChange, this));
|
|
}
|
|
|
|
std::shared_ptr<pdx::Channel> 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<DisplayManager>(this, message.GetChannelId());
|
|
return display_manager_;
|
|
}
|
|
|
|
void DisplayManagerService::OnChannelClose(
|
|
pdx::Message& /*message*/, const std::shared_ptr<pdx::Channel>& channel) {
|
|
// Unregister the display manager when the channel closes.
|
|
if (display_manager_ == channel)
|
|
display_manager_ = nullptr;
|
|
}
|
|
|
|
pdx::Status<void> DisplayManagerService::HandleMessage(pdx::Message& message) {
|
|
ATRACE_NAME("DisplayManagerService::HandleMessage");
|
|
auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
|
|
|
|
switch (message.GetOp()) {
|
|
case DisplayManagerProtocol::GetSurfaceState::Opcode:
|
|
DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceState>(
|
|
*this, &DisplayManagerService::OnGetSurfaceState, message);
|
|
return {};
|
|
|
|
case DisplayManagerProtocol::GetSurfaceQueue::Opcode:
|
|
DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
|
|
*this, &DisplayManagerService::OnGetSurfaceQueue, message);
|
|
return {};
|
|
|
|
default:
|
|
return Service::DefaultHandleMessage(message);
|
|
}
|
|
}
|
|
|
|
pdx::Status<std::vector<display::SurfaceState>>
|
|
DisplayManagerService::OnGetSurfaceState(pdx::Message& /*message*/) {
|
|
std::vector<display::SurfaceState> items;
|
|
|
|
display_service_->ForEachDisplaySurface(
|
|
SurfaceType::Application,
|
|
[&items](const std::shared_ptr<DisplaySurface>& 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<pdx::LocalChannelHandle> 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<ApplicationDisplaySurface>(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
|