display_service.cpp revision 356bc37719bb748346a79935e1979e264c81c296
1#include "display_service.h"
2
3#include <vector>
4
5#include <pdx/default_transport/service_endpoint.h>
6#include <pdx/rpc/remote_method.h>
7#include <private/dvr/composite_hmd.h>
8#include <private/dvr/display_rpc.h>
9#include <private/dvr/display_types.h>
10#include <private/dvr/lucid_metrics.h>
11#include <private/dvr/numeric.h>
12#include <private/dvr/polynomial_radial_distortion.h>
13#include <private/dvr/types.h>
14
15using android::pdx::Channel;
16using android::pdx::Message;
17using android::pdx::default_transport::Endpoint;
18using android::pdx::rpc::DispatchRemoteMethod;
19using android::pdx::rpc::WrapBuffer;
20
21namespace {
22
23constexpr char kPersistentPoseBufferName[] = "DvrPersistentPoseBuffer";
24const int kPersistentPoseBufferUserId = 0;
25const int kPersistentPoseBufferGroupId = 0;
26const size_t kTimingDataSizeOffset = 128;
27
28}  // anonymous namespace
29
30namespace android {
31namespace dvr {
32
33DisplayService::DisplayService()
34    : DisplayService(nullptr) {}
35
36DisplayService::DisplayService(Hwc2::Composer* hidl)
37    : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
38      hardware_composer_(hidl) {
39  hardware_composer_.Initialize();
40}
41
42bool DisplayService::IsInitialized() const {
43  return BASE::IsInitialized() && hardware_composer_.IsInitialized();
44}
45
46std::string DisplayService::DumpState(size_t max_length) {
47  std::vector<char> buffer(max_length);
48  uint32_t max_len_p = static_cast<uint32_t>(max_length);
49  hardware_composer_.Dump(buffer.data(), &max_len_p);
50  return std::string(buffer.data());
51}
52
53void DisplayService::OnChannelClose(pdx::Message& /*message*/,
54                                    const std::shared_ptr<Channel>& channel) {
55  auto surface = std::static_pointer_cast<SurfaceChannel>(channel);
56  if (surface && surface->type() == SurfaceTypeEnum::Normal) {
57    auto display_surface = std::static_pointer_cast<DisplaySurface>(surface);
58    display_surface->ManagerSetVisible(false);
59    display_surface->ClientSetVisible(false);
60    NotifyDisplayConfigurationUpdate();
61  }
62  // TODO(jwcai) Handle ChannelClose of VideoMeshSurface.
63}
64
65// First-level dispatch for display service messages. Directly handles messages
66// that are independent of the display surface (metrics, creation) and routes
67// surface-specific messages to the per-instance handlers.
68pdx::Status<void> DisplayService::HandleMessage(pdx::Message& message) {
69  auto channel = message.GetChannel<SurfaceChannel>();
70
71  switch (message.GetOp()) {
72    case DisplayRPC::GetMetrics::Opcode:
73      DispatchRemoteMethod<DisplayRPC::GetMetrics>(
74          *this, &DisplayService::OnGetMetrics, message);
75      return {};
76
77    case DisplayRPC::GetEdsCapture::Opcode:
78      DispatchRemoteMethod<DisplayRPC::GetEdsCapture>(
79          *this, &DisplayService::OnGetEdsCapture, message);
80      return {};
81
82    case DisplayRPC::CreateSurface::Opcode:
83      DispatchRemoteMethod<DisplayRPC::CreateSurface>(
84          *this, &DisplayService::OnCreateSurface, message);
85      return {};
86
87    case DisplayRPC::SetViewerParams::Opcode:
88      DispatchRemoteMethod<DisplayRPC::SetViewerParams>(
89          *this, &DisplayService::OnSetViewerParams, message);
90      return {};
91
92    case DisplayRPC::GetPoseBuffer::Opcode:
93      DispatchRemoteMethod<DisplayRPC::GetPoseBuffer>(
94          *this, &DisplayService::OnGetPoseBuffer, message);
95      return {};
96
97    case DisplayRPC::IsVrAppRunning::Opcode:
98      DispatchRemoteMethod<DisplayRPC::IsVrAppRunning>(
99          *this, &DisplayService::IsVrAppRunning, message);
100      return {};
101
102    // Direct the surface specific messages to the surface instance.
103    case DisplayRPC::CreateBufferQueue::Opcode:
104    case DisplayRPC::SetAttributes::Opcode:
105    case DisplayRPC::GetMetadataBuffer::Opcode:
106    case DisplayRPC::CreateVideoMeshSurface::Opcode:
107    case DisplayRPC::VideoMeshSurfaceCreateProducerQueue::Opcode:
108      return HandleSurfaceMessage(message);
109
110    default:
111      return Service::HandleMessage(message);
112  }
113}
114
115SystemDisplayMetrics DisplayService::OnGetMetrics(pdx::Message& message) {
116  const Compositor* compositor = hardware_composer_.GetCompositor();
117  if (compositor == nullptr)
118    REPLY_ERROR_RETURN(message, EINVAL, {});
119
120  HeadMountMetrics head_mount = compositor->head_mount_metrics();
121  CompositeHmd hmd(head_mount, hardware_composer_.GetHmdDisplayMetrics());
122  vec2i distorted_render_size = hmd.GetRecommendedRenderTargetSize();
123  FieldOfView left_fov = hmd.GetEyeFov(kLeftEye);
124  FieldOfView right_fov = hmd.GetEyeFov(kRightEye);
125
126  SystemDisplayMetrics metrics;
127
128  metrics.display_native_width = GetDisplayMetrics().width;
129  metrics.display_native_height = GetDisplayMetrics().height;
130  metrics.display_x_dpi = GetDisplayMetrics().dpi.x;
131  metrics.display_y_dpi = GetDisplayMetrics().dpi.y;
132  metrics.distorted_width = distorted_render_size[0];
133  metrics.distorted_height = distorted_render_size[1];
134  metrics.vsync_period_ns =
135      hardware_composer_.native_display_metrics().vsync_period_ns;
136  metrics.hmd_ipd_mm = 0;
137  metrics.inter_lens_distance_m = head_mount.GetInterLensDistance();
138  metrics.left_fov_lrbt[0] = left_fov.GetLeft();
139  metrics.left_fov_lrbt[1] = left_fov.GetRight();
140  metrics.left_fov_lrbt[2] = left_fov.GetBottom();
141  metrics.left_fov_lrbt[3] = left_fov.GetTop();
142  metrics.right_fov_lrbt[0] = right_fov.GetLeft();
143  metrics.right_fov_lrbt[1] = right_fov.GetRight();
144  metrics.right_fov_lrbt[2] = right_fov.GetBottom();
145  metrics.right_fov_lrbt[3] = right_fov.GetTop();
146
147  return metrics;
148}
149
150// Creates a new DisplaySurface and associates it with this channel. This may
151// only be done once per channel.
152int DisplayService::OnCreateSurface(pdx::Message& message, int width,
153                                    int height, int format, int usage,
154                                    DisplaySurfaceFlags flags) {
155  // A surface may only be created once per channel.
156  if (message.GetChannel())
157    return -EINVAL;
158
159  ALOGI_IF(TRACE, "DisplayService::OnCreateSurface: cid=%d",
160           message.GetChannelId());
161
162  // Use the channel id as the unique surface id.
163  const int surface_id = message.GetChannelId();
164  const int process_id = message.GetProcessId();
165
166  ALOGI_IF(TRACE,
167           "DisplayService::OnCreateSurface: surface_id=%d process_id=%d "
168           "width=%d height=%d format=%x usage=%x flags=%x",
169           surface_id, process_id, width, height, format, usage, flags);
170
171  // TODO(eieio,jbates): Validate request parameters.
172  auto channel = std::make_shared<DisplaySurface>(
173      this, surface_id, process_id, width, height, format, usage, flags);
174
175  message.SetChannel(channel);
176  NotifyDisplayConfigurationUpdate();
177  return 0;
178}
179
180DisplayRPC::ByteBuffer DisplayService::OnGetEdsCapture(pdx::Message& message) {
181  Compositor* compositor = hardware_composer_.GetCompositor();
182  if (compositor == nullptr)
183    REPLY_ERROR_RETURN(message, EINVAL, {});
184
185  std::vector<std::uint8_t> buffer(sizeof(LateLatchOutput));
186
187  if (!compositor->GetLastEdsPose(
188          reinterpret_cast<LateLatchOutput*>(buffer.data()))) {
189    REPLY_ERROR_RETURN(message, EPERM, {});
190  }
191
192  return WrapBuffer(std::move(buffer));
193}
194
195void DisplayService::OnSetViewerParams(pdx::Message& message,
196                                       const ViewerParams& view_params) {
197  Compositor* compositor = hardware_composer_.GetCompositor();
198  if (compositor == nullptr)
199    REPLY_ERROR_RETURN(message, EINVAL);
200
201  FieldOfView left(55.0f, 55.0f, 55.0f, 55.0f);
202  FieldOfView right(55.0f, 55.0f, 55.0f, 55.0f);
203  if (view_params.left_eye_field_of_view_angles.size() >= 4) {
204    left = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[0]),
205                       ToRad(view_params.left_eye_field_of_view_angles[1]),
206                       ToRad(view_params.left_eye_field_of_view_angles[2]),
207                       ToRad(view_params.left_eye_field_of_view_angles[3]));
208    right = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[1]),
209                        ToRad(view_params.left_eye_field_of_view_angles[0]),
210                        ToRad(view_params.left_eye_field_of_view_angles[2]),
211                        ToRad(view_params.left_eye_field_of_view_angles[3]));
212  }
213
214  std::shared_ptr<ColorChannelDistortion> red_distortion;
215  std::shared_ptr<ColorChannelDistortion> green_distortion;
216  std::shared_ptr<ColorChannelDistortion> blue_distortion;
217
218  // We should always have a red distortion.
219  LOG_FATAL_IF(view_params.distortion_coefficients_r.empty());
220  red_distortion = std::make_shared<PolynomialRadialDistortion>(
221      view_params.distortion_coefficients_r);
222
223  if (!view_params.distortion_coefficients_g.empty()) {
224    green_distortion = std::make_shared<PolynomialRadialDistortion>(
225        view_params.distortion_coefficients_g);
226  }
227
228  if (!view_params.distortion_coefficients_b.empty()) {
229    blue_distortion = std::make_shared<PolynomialRadialDistortion>(
230        view_params.distortion_coefficients_b);
231  }
232
233  HeadMountMetrics::EyeOrientation left_orientation =
234      HeadMountMetrics::EyeOrientation::kCCW0Degrees;
235  HeadMountMetrics::EyeOrientation right_orientation =
236      HeadMountMetrics::EyeOrientation::kCCW0Degrees;
237
238  if (view_params.eye_orientations.size() > 1) {
239    left_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
240        view_params.eye_orientations[0]);
241    right_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
242        view_params.eye_orientations[1]);
243  }
244
245  HeadMountMetrics head_mount_metrics(
246      view_params.inter_lens_distance, view_params.tray_to_lens_distance,
247      view_params.screen_to_lens_distance,
248      static_cast<HeadMountMetrics::VerticalAlignment>(
249          view_params.vertical_alignment),
250      left, right, red_distortion, green_distortion, blue_distortion,
251      left_orientation, right_orientation,
252      view_params.screen_center_to_lens_distance);
253
254  compositor->UpdateHeadMountMetrics(head_mount_metrics);
255}
256
257pdx::LocalChannelHandle DisplayService::OnGetPoseBuffer(pdx::Message& message) {
258  if (pose_buffer_) {
259    return pose_buffer_->CreateConsumer().take();
260  }
261
262  pdx::rpc::RemoteMethodError(message, EAGAIN);
263  return {};
264}
265
266// Calls the message handler for the DisplaySurface associated with this
267// channel.
268pdx::Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
269  auto surface = std::static_pointer_cast<SurfaceChannel>(message.GetChannel());
270  ALOGW_IF(!surface,
271           "DisplayService::HandleSurfaceMessage: surface is nullptr!");
272
273  if (surface)
274    return surface->HandleMessage(message);
275  else
276    REPLY_ERROR_RETURN(message, EINVAL, {});
277}
278
279std::shared_ptr<DisplaySurface> DisplayService::GetDisplaySurface(
280    int surface_id) const {
281  return std::static_pointer_cast<DisplaySurface>(GetChannel(surface_id));
282}
283
284std::vector<std::shared_ptr<DisplaySurface>>
285DisplayService::GetDisplaySurfaces() const {
286  return GetChannels<DisplaySurface>();
287}
288
289std::vector<std::shared_ptr<DisplaySurface>>
290DisplayService::GetVisibleDisplaySurfaces() const {
291  std::vector<std::shared_ptr<DisplaySurface>> visible_surfaces;
292
293  ForEachDisplaySurface(
294      [&](const std::shared_ptr<DisplaySurface>& surface) mutable {
295        if (surface->IsVisible())
296          visible_surfaces.push_back(surface);
297      });
298
299  return visible_surfaces;
300}
301
302void DisplayService::UpdateActiveDisplaySurfaces() {
303  auto visible_surfaces = GetVisibleDisplaySurfaces();
304
305  // Sort the surfaces based on manager z order first, then client z order.
306  std::sort(visible_surfaces.begin(), visible_surfaces.end(),
307            [](const std::shared_ptr<DisplaySurface>& a,
308               const std::shared_ptr<DisplaySurface>& b) {
309              return a->manager_z_order() != b->manager_z_order()
310                         ? a->manager_z_order() < b->manager_z_order()
311                         : a->client_z_order() < b->client_z_order();
312            });
313
314  ALOGD_IF(TRACE,
315           "DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces",
316           visible_surfaces.size());
317
318  // TODO(jbates) Have the shell manage blurred layers.
319  bool blur_requested = false;
320  auto end = visible_surfaces.crend();
321  for (auto it = visible_surfaces.crbegin(); it != end; ++it) {
322    auto surface = *it;
323    // Surfaces with exclude_from_blur==true are not blurred
324    // and are excluded from blur computation of other layers.
325    if (surface->client_exclude_from_blur()) {
326      surface->ManagerSetBlur(0.0f);
327      continue;
328    }
329    surface->ManagerSetBlur(blur_requested ? 1.0f : 0.0f);
330    if (surface->client_blur_behind())
331      blur_requested = true;
332  }
333
334  hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
335}
336
337pdx::BorrowedChannelHandle DisplayService::SetupPoseBuffer(
338    size_t extended_region_size, int usage) {
339  if (!pose_buffer_) {
340    pose_buffer_ = BufferProducer::Create(
341        kPersistentPoseBufferName, kPersistentPoseBufferUserId,
342        kPersistentPoseBufferGroupId, usage,
343        extended_region_size + kTimingDataSizeOffset);
344  }
345
346  return pose_buffer_->GetChannelHandle().Borrow();
347}
348
349void DisplayService::OnHardwareComposerRefresh() {
350  hardware_composer_.OnHardwareComposerRefresh();
351}
352
353void DisplayService::SetDisplayConfigurationUpdateNotifier(
354    DisplayConfigurationUpdateNotifier update_notifier) {
355  update_notifier_ = update_notifier;
356}
357
358void DisplayService::NotifyDisplayConfigurationUpdate() {
359  if (update_notifier_)
360    update_notifier_();
361}
362
363int DisplayService::IsVrAppRunning(pdx::Message& message) {
364  bool visible = false;
365  ForEachDisplaySurface([&visible](const std::shared_ptr<DisplaySurface>& surface) {
366    if (surface->client_z_order() == 0 && surface->IsVisible())
367      visible = true;
368  });
369
370  REPLY_SUCCESS_RETURN(message, visible, 0);
371}
372
373}  // namespace dvr
374}  // namespace android
375