display_manager_service.cpp revision a8a92784bc5f6a50ce00311c6161fbcfc0898c5a
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  int ret = service_->ModifyChannelEvents(channel_id_, pending ? 0 : POLLIN,
36                                          pending ? POLLIN : 0);
37  ALOGE_IF(ret < 0,
38           "DisplayManager::SetNotificationPending: Failed to modify channel "
39           "events: %s",
40           strerror(-ret));
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
71int 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 0;
79
80    case DisplayManagerRPC::GetSurfaceBuffers::Opcode:
81      DispatchRemoteMethod<DisplayManagerRPC::GetSurfaceBuffers>(
82          *this, &DisplayManagerService::OnGetSurfaceBuffers, message);
83      return 0;
84
85    case DisplayManagerRPC::UpdateSurfaces::Opcode:
86      DispatchRemoteMethod<DisplayManagerRPC::UpdateSurfaces>(
87          *this, &DisplayManagerService::OnUpdateSurfaces, message);
88      return 0;
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([&items](
100      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, DisplaySurfaceAttributeValue{0.f}}};
113    item.manager_attributes = DisplaySurfaceAttributes{
114        {DisplaySurfaceAttributeEnum::Visible,
115         DisplaySurfaceAttributeValue{surface->manager_visible()}},
116        {DisplaySurfaceAttributeEnum::ZOrder,
117         DisplaySurfaceAttributeValue{surface->manager_z_order()}},
118        {DisplaySurfaceAttributeEnum::Blur,
119         DisplaySurfaceAttributeValue{surface->manager_blur()}}};
120
121    items.push_back(item);
122  });
123
124  // The fact that we're in the message handler implies that display_manager_ is
125  // not nullptr. No check required, unless this service becomes multi-threaded.
126  display_manager_->SetNotificationsPending(false);
127
128  return items;
129}
130
131std::vector<LocalChannelHandle> DisplayManagerService::OnGetSurfaceBuffers(
132    pdx::Message& message, int surface_id) {
133  std::shared_ptr<DisplaySurface> surface =
134      display_service_->GetDisplaySurface(surface_id);
135  if (!surface)
136    REPLY_ERROR_RETURN(message, ENOENT, {});
137
138  std::vector<LocalChannelHandle> consumers;
139  int ret = surface->GetConsumers(&consumers);
140  if (ret < 0) {
141    ALOGE(
142        "DisplayManagerService::OnGetDisplaySurfaceBuffers: Failed to get "
143        "consumers for surface %d: %s",
144        surface_id, strerror(-ret));
145    REPLY_ERROR_RETURN(message, -ret, {});
146  }
147
148  return consumers;
149}
150
151int DisplayManagerService::OnUpdateSurfaces(
152    pdx::Message& /*message*/,
153    const std::map<int, DisplaySurfaceAttributes>& updates) {
154  for (const auto& surface_update : updates) {
155    const int surface_id = surface_update.first;
156    const DisplaySurfaceAttributes& attributes = surface_update.second;
157
158    std::shared_ptr<DisplaySurface> surface =
159        display_service_->GetDisplaySurface(surface_id);
160
161    if (!surface)
162      return -ENOENT;
163
164    for (const auto& attribute : attributes) {
165      const auto& key = attribute.first;
166      const auto* variant = &attribute.second;
167      bool invalid_value = false;
168      switch (key) {
169        case DisplaySurfaceAttributeEnum::ZOrder:
170          invalid_value =
171              !IfAnyOf<int32_t>::Call(variant, [&surface](const auto& value) {
172                surface->ManagerSetZOrder(value);
173              });
174          break;
175        case DisplaySurfaceAttributeEnum::Visible:
176          invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
177              variant, [&surface](const auto& value) {
178                surface->ManagerSetVisible(value);
179              });
180          break;
181        case DisplaySurfaceAttributeEnum::Blur:
182          invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
183              variant, [&surface](const auto& value) {
184                surface->ManagerSetBlur(value);
185              });
186          break;
187        default:
188          ALOGW(
189              "DisplayManagerService::OnUpdateSurfaces: Attempt to set invalid "
190              "attribute %u on surface %d",
191              key, surface_id);
192          break;
193      }
194
195      if (invalid_value) {
196        ALOGW(
197            "DisplayManagerService::OnUpdateSurfaces: Failed to set display "
198            "surface attribute '%s' because of incompatible type: %d",
199            DisplaySurfaceAttributeEnum::ToString(key).c_str(),
200            variant->index());
201      }
202    }
203  }
204
205  // Reconfigure the display layers for any active surface changes.
206  display_service_->UpdateActiveDisplaySurfaces();
207  return 0;
208}
209
210void DisplayManagerService::OnDisplaySurfaceChange() {
211  if (display_manager_) {
212    display_manager_->SetNotificationsPending(true);
213  } else {
214    // If there isn't a display manager registered, default all display surfaces
215    // to visible.
216    display_service_->ForEachDisplaySurface(
217        [](const std::shared_ptr<DisplaySurface>& surface) {
218          surface->ManagerSetVisible(true);
219        });
220    display_service_->UpdateActiveDisplaySurfaces();
221  }
222}
223
224}  // namespace dvr
225}  // namespace android
226