display_manager_service.cpp revision f0a7bd033941e26e380232a0515e903cf8e678e5
1#include "display_manager_service.h"
2
3#include <pdx/channel_handle.h>
4#include <pdx/default_transport/service_endpoint.h>
5#include <private/dvr/display_rpc.h>
6#include <sys/poll.h>
7
8#include <array>
9
10using android::pdx::Channel;
11using android::pdx::LocalChannelHandle;
12using android::pdx::Message;
13using android::pdx::default_transport::Endpoint;
14using android::pdx::rpc::DispatchRemoteMethod;
15using android::pdx::rpc::IfAnyOf;
16
17namespace {
18
19// As a first line of defense, the display manager endpoint is only accessible
20// to the user and group.
21
22// TODO(dnicoara): Remove read/write permission for others. This is in here just
23// to allow us to experiment with cast functionality from a plain old app.
24constexpr mode_t kDisplayManagerEndpointFileMode =
25    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
26
27constexpr size_t kMaxSurfacesPerRequest = 32;
28
29}  // anonymous namespace
30
31namespace android {
32namespace dvr {
33
34void DisplayManager::SetNotificationsPending(bool pending) {
35  auto status = service_->ModifyChannelEvents(channel_id_, pending ? 0 : POLLIN,
36                                              pending ? POLLIN : 0);
37  ALOGE_IF(!status,
38           "DisplayManager::SetNotificationPending: Failed to modify channel "
39           "events: %s",
40           status.GetErrorMessage().c_str());
41}
42
43DisplayManagerService::DisplayManagerService(
44    const std::shared_ptr<DisplayService>& display_service)
45    : BASE("DisplayManagerService",
46           Endpoint::Create(DisplayManagerRPC::kClientPath,
47                            kDisplayManagerEndpointFileMode)),
48      display_service_(display_service) {
49  display_service_->SetDisplayConfigurationUpdateNotifier(
50      std::bind(&DisplayManagerService::OnDisplaySurfaceChange, this));
51}
52
53std::shared_ptr<pdx::Channel> DisplayManagerService::OnChannelOpen(
54    pdx::Message& message) {
55  // Prevent more than one display manager from registering at a time.
56  if (display_manager_)
57    REPLY_ERROR_RETURN(message, EPERM, nullptr);
58
59  display_manager_ =
60      std::make_shared<DisplayManager>(this, message.GetChannelId());
61  return display_manager_;
62}
63
64void DisplayManagerService::OnChannelClose(
65    pdx::Message& /*message*/, const std::shared_ptr<pdx::Channel>& channel) {
66  // Unregister the display manager when the channel closes.
67  if (display_manager_ == channel)
68    display_manager_ = nullptr;
69}
70
71pdx::Status<void> DisplayManagerService::HandleMessage(pdx::Message& message) {
72  auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
73
74  switch (message.GetOp()) {
75    case DisplayManagerRPC::GetSurfaceList::Opcode:
76      DispatchRemoteMethod<DisplayManagerRPC::GetSurfaceList>(
77          *this, &DisplayManagerService::OnGetSurfaceList, message);
78      return {};
79
80    case DisplayManagerRPC::UpdateSurfaces::Opcode:
81      DispatchRemoteMethod<DisplayManagerRPC::UpdateSurfaces>(
82          *this, &DisplayManagerService::OnUpdateSurfaces, message);
83      return {};
84
85  case DisplayManagerRPC::SetupPoseBuffer::Opcode:
86      DispatchRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
87          *this, &DisplayManagerService::OnSetupPoseBuffer, message);
88      return {};
89
90    default:
91      return Service::DefaultHandleMessage(message);
92  }
93}
94
95std::vector<DisplaySurfaceInfo> DisplayManagerService::OnGetSurfaceList(
96    pdx::Message& /*message*/) {
97  std::vector<DisplaySurfaceInfo> items;
98
99  display_service_->ForEachDisplaySurface(
100      [&items](const std::shared_ptr<DisplaySurface>& surface) mutable {
101        DisplaySurfaceInfo item;
102
103        item.surface_id = surface->surface_id();
104        item.process_id = surface->process_id();
105        item.type = surface->type();
106        item.flags = 0;  // TODO(eieio)
107        item.client_attributes = DisplaySurfaceAttributes{
108            {DisplaySurfaceAttributeEnum::Visible,
109             DisplaySurfaceAttributeValue{surface->client_visible()}},
110            {DisplaySurfaceAttributeEnum::ZOrder,
111             DisplaySurfaceAttributeValue{surface->client_z_order()}},
112            {DisplaySurfaceAttributeEnum::Blur,
113             DisplaySurfaceAttributeValue{0.f}}};
114        item.manager_attributes = DisplaySurfaceAttributes{
115            {DisplaySurfaceAttributeEnum::Visible,
116             DisplaySurfaceAttributeValue{surface->manager_visible()}},
117            {DisplaySurfaceAttributeEnum::ZOrder,
118             DisplaySurfaceAttributeValue{surface->manager_z_order()}},
119            {DisplaySurfaceAttributeEnum::Blur,
120             DisplaySurfaceAttributeValue{surface->manager_blur()}}};
121
122        items.push_back(item);
123      });
124
125  // The fact that we're in the message handler implies that display_manager_ is
126  // not nullptr. No check required, unless this service becomes multi-threaded.
127  display_manager_->SetNotificationsPending(false);
128
129  return items;
130}
131
132int DisplayManagerService::OnUpdateSurfaces(
133    pdx::Message& /*message*/,
134    const std::map<int, DisplaySurfaceAttributes>& updates) {
135  for (const auto& surface_update : updates) {
136    const int surface_id = surface_update.first;
137    const DisplaySurfaceAttributes& attributes = surface_update.second;
138
139    std::shared_ptr<DisplaySurface> surface =
140        display_service_->GetDisplaySurface(surface_id);
141
142    if (!surface)
143      return -ENOENT;
144
145    for (const auto& attribute : attributes) {
146      const auto& key = attribute.first;
147      const auto* variant = &attribute.second;
148      bool invalid_value = false;
149      switch (key) {
150        case DisplaySurfaceAttributeEnum::ZOrder:
151          invalid_value =
152              !IfAnyOf<int32_t>::Call(variant, [&surface](const auto& value) {
153                surface->ManagerSetZOrder(value);
154              });
155          break;
156        case DisplaySurfaceAttributeEnum::Visible:
157          invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
158              variant, [&surface](const auto& value) {
159                surface->ManagerSetVisible(value);
160              });
161          break;
162        case DisplaySurfaceAttributeEnum::Blur:
163          invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
164              variant, [&surface](const auto& value) {
165                surface->ManagerSetBlur(value);
166              });
167          break;
168        default:
169          ALOGW(
170              "DisplayManagerService::OnUpdateSurfaces: Attempt to set invalid "
171              "attribute %u on surface %d",
172              key, surface_id);
173          break;
174      }
175
176      if (invalid_value) {
177        ALOGW(
178            "DisplayManagerService::OnUpdateSurfaces: Failed to set display "
179            "surface attribute '%s' because of incompatible type: %d",
180            DisplaySurfaceAttributeEnum::ToString(key).c_str(),
181            variant->index());
182      }
183    }
184  }
185
186  // Reconfigure the display layers for any active surface changes.
187  display_service_->UpdateActiveDisplaySurfaces();
188  return 0;
189}
190
191pdx::BorrowedChannelHandle DisplayManagerService::OnSetupPoseBuffer(
192    pdx::Message& /*message*/, size_t extended_region_size, int usage) {
193  return display_service_->SetupPoseBuffer(extended_region_size, usage);
194}
195
196void DisplayManagerService::OnDisplaySurfaceChange() {
197  if (display_manager_) {
198    display_manager_->SetNotificationsPending(true);
199  } else {
200    // If there isn't a display manager registered, default all display surfaces
201    // to visible.
202    display_service_->ForEachDisplaySurface(
203        [](const std::shared_ptr<DisplaySurface>& surface) {
204          surface->ManagerSetVisible(true);
205        });
206    display_service_->UpdateActiveDisplaySurfaces();
207  }
208}
209
210}  // namespace dvr
211}  // namespace android
212