1#include "display_manager_service.h"
2
3#include <pdx/channel_handle.h>
4#include <pdx/default_transport/service_endpoint.h>
5#include <private/android_filesystem_config.h>
6#include <private/dvr/display_protocol.h>
7#include <private/dvr/trusted_uids.h>
8#include <sys/poll.h>
9
10#include <array>
11
12using android::dvr::display::DisplayManagerProtocol;
13using android::pdx::Channel;
14using android::pdx::LocalChannelHandle;
15using android::pdx::Message;
16using android::pdx::default_transport::Endpoint;
17using android::pdx::ErrorStatus;
18using android::pdx::rpc::DispatchRemoteMethod;
19using android::pdx::rpc::IfAnyOf;
20using android::pdx::rpc::RemoteMethodError;
21
22namespace android {
23namespace dvr {
24
25void DisplayManager::SetNotificationsPending(bool pending) {
26  auto status = service_->ModifyChannelEvents(channel_id_, pending ? 0 : POLLIN,
27                                              pending ? POLLIN : 0);
28  ALOGE_IF(!status,
29           "DisplayManager::SetNotificationPending: Failed to modify channel "
30           "events: %s",
31           status.GetErrorMessage().c_str());
32}
33
34DisplayManagerService::DisplayManagerService(
35    const std::shared_ptr<DisplayService>& display_service)
36    : BASE("DisplayManagerService",
37           Endpoint::Create(DisplayManagerProtocol::kClientPath)),
38      display_service_(display_service) {
39  display_service_->SetDisplayConfigurationUpdateNotifier(
40      std::bind(&DisplayManagerService::OnDisplaySurfaceChange, this));
41}
42
43std::shared_ptr<pdx::Channel> DisplayManagerService::OnChannelOpen(
44    pdx::Message& message) {
45  const int user_id = message.GetEffectiveUserId();
46  const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
47
48  // Check if the display_manager_ has a defunct channel.
49  if (display_manager_ && !HasChannelId(display_manager_->channel_id())) {
50    ALOGE("DisplayManagerService::OnChannelOpen: Found defunct channel %d with "
51          "no OnChannelClose, clearing prior display manager.",
52          display_manager_->channel_id());
53    display_manager_ = nullptr;
54  }
55
56  // Prevent more than one display manager from registering at a time or
57  // untrusted UIDs from connecting.
58  if (display_manager_ || !trusted) {
59    RemoteMethodError(message, EPERM);
60    return nullptr;
61  }
62
63  display_manager_ =
64      std::make_shared<DisplayManager>(this, message.GetChannelId());
65  return display_manager_;
66}
67
68void DisplayManagerService::OnChannelClose(
69    pdx::Message& /*message*/, const std::shared_ptr<pdx::Channel>& channel) {
70  // Unregister the display manager when the channel closes.
71  if (display_manager_ == channel)
72    display_manager_ = nullptr;
73}
74
75pdx::Status<void> DisplayManagerService::HandleMessage(pdx::Message& message) {
76  ATRACE_NAME("DisplayManagerService::HandleMessage");
77  auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
78
79  switch (message.GetOp()) {
80    case DisplayManagerProtocol::GetSurfaceState::Opcode:
81      DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceState>(
82          *this, &DisplayManagerService::OnGetSurfaceState, message);
83      return {};
84
85    case DisplayManagerProtocol::GetSurfaceQueue::Opcode:
86      DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
87          *this, &DisplayManagerService::OnGetSurfaceQueue, message);
88      return {};
89
90    default:
91      return Service::DefaultHandleMessage(message);
92  }
93}
94
95pdx::Status<std::vector<display::SurfaceState>>
96DisplayManagerService::OnGetSurfaceState(pdx::Message& /*message*/) {
97  std::vector<display::SurfaceState> items;
98
99  display_service_->ForEachDisplaySurface(
100      SurfaceType::Application,
101      [&items](const std::shared_ptr<DisplaySurface>& surface) mutable {
102        items.push_back({surface->surface_id(), surface->process_id(),
103                         surface->user_id(), surface->attributes(),
104                         surface->update_flags(), surface->GetQueueIds()});
105        surface->ClearUpdate();
106      });
107
108  // The fact that we're in the message handler implies that display_manager_ is
109  // not nullptr. No check required, unless this service becomes multi-threaded.
110  display_manager_->SetNotificationsPending(false);
111  return items;
112}
113
114pdx::Status<pdx::LocalChannelHandle> DisplayManagerService::OnGetSurfaceQueue(
115    pdx::Message& /*message*/, int surface_id, int queue_id) {
116  auto surface = display_service_->GetDisplaySurface(surface_id);
117  if (!surface || surface->surface_type() != SurfaceType::Application)
118    return ErrorStatus(EINVAL);
119
120  auto queue =
121      std::static_pointer_cast<ApplicationDisplaySurface>(surface)->GetQueue(
122          queue_id);
123  if (!queue)
124    return ErrorStatus(EINVAL);
125
126  auto status = queue->CreateConsumerQueueHandle();
127  ALOGE_IF(
128      !status,
129      "DisplayManagerService::OnGetSurfaceQueue: Failed to create consumer "
130      "queue for queue_id=%d: %s",
131      queue->id(), status.GetErrorMessage().c_str());
132
133  return status;
134}
135
136void DisplayManagerService::OnDisplaySurfaceChange() {
137  if (display_manager_)
138    display_manager_->SetNotificationsPending(true);
139}
140
141}  // namespace dvr
142}  // namespace android
143