display_client.cpp revision 2251d822dac2a96aad4184a6fdc2690f0a58af7c
1#include "include/private/dvr/display_client.h"
2
3#include <cutils/native_handle.h>
4#include <log/log.h>
5#include <pdx/default_transport/client_channel.h>
6#include <pdx/default_transport/client_channel_factory.h>
7#include <pdx/status.h>
8
9#include <mutex>
10
11#include <private/dvr/display_protocol.h>
12#include <private/dvr/late_latch.h>
13#include <private/dvr/native_buffer.h>
14
15using android::pdx::ErrorStatus;
16using android::pdx::LocalHandle;
17using android::pdx::LocalChannelHandle;
18using android::pdx::Status;
19using android::pdx::Transaction;
20using android::pdx::rpc::IfAnyOf;
21
22namespace android {
23namespace dvr {
24namespace display {
25
26Surface::Surface(LocalChannelHandle channel_handle, int* error)
27    : BASE{pdx::default_transport::ClientChannel::Create(
28          std::move(channel_handle))} {
29  auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>();
30  if (!status) {
31    ALOGE("Surface::Surface: Failed to get surface info: %s",
32          status.GetErrorMessage().c_str());
33    Close(status.error());
34    if (error)
35      *error = status.error();
36  }
37
38  surface_id_ = status.get().surface_id;
39  z_order_ = status.get().z_order;
40  visible_ = status.get().visible;
41}
42
43Surface::Surface(const SurfaceAttributes& attributes, int* error)
44    : BASE{pdx::default_transport::ClientChannelFactory::Create(
45               DisplayProtocol::kClientPath),
46           kInfiniteTimeout} {
47  auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes);
48  if (!status) {
49    ALOGE("Surface::Surface: Failed to create display surface: %s",
50          status.GetErrorMessage().c_str());
51    Close(status.error());
52    if (error)
53      *error = status.error();
54  }
55
56  surface_id_ = status.get().surface_id;
57  z_order_ = status.get().z_order;
58  visible_ = status.get().visible;
59}
60
61Status<void> Surface::SetVisible(bool visible) {
62  return SetAttributes(
63      {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
64}
65
66Status<void> Surface::SetZOrder(int z_order) {
67  return SetAttributes(
68      {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
69}
70
71Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
72  auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
73  if (!status) {
74    ALOGE(
75        "Surface::SetAttributes: Failed to set display surface "
76        "attributes: %s",
77        status.GetErrorMessage().c_str());
78    return status.error_status();
79  }
80
81  // Set the local cached copies of the attributes we care about from the full
82  // set of attributes sent to the display service.
83  for (const auto& attribute : attributes) {
84    const auto& key = attribute.first;
85    const auto* variant = &attribute.second;
86    bool invalid_value = false;
87    switch (key) {
88      case SurfaceAttribute::Visible:
89        invalid_value =
90            !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
91        break;
92      case SurfaceAttribute::ZOrder:
93        invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
94        break;
95    }
96
97    if (invalid_value) {
98      ALOGW(
99          "Surface::SetAttributes: Failed to set display surface "
100          "attribute %d because of incompatible type: %d",
101          key, variant->index());
102    }
103  }
104
105  return {};
106}
107
108Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() {
109  ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
110  auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0);
111  if (!status) {
112    ALOGE("Surface::CreateQueue: Failed to create queue: %s",
113          status.GetErrorMessage().c_str());
114    return status.error_status();
115  }
116
117  auto producer_queue = ProducerQueue::Import(status.take());
118  if (!producer_queue) {
119    ALOGE("Surface::CreateQueue: Failed to import producer queue!");
120    return ErrorStatus(ENOMEM);
121  }
122
123  return {std::move(producer_queue)};
124}
125
126Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(uint32_t width,
127                                                            uint32_t height,
128                                                            uint32_t format,
129                                                            uint64_t usage,
130                                                            size_t capacity) {
131  ALOGD_IF(TRACE,
132           "Surface::CreateQueue: width=%u height=%u format=%u usage=%" PRIx64
133           " capacity=%zu",
134           width, height, format, usage, capacity);
135  auto status = CreateQueue();
136  if (!status)
137    return status.error_status();
138
139  auto producer_queue = status.take();
140
141  ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
142  for (size_t i = 0; i < capacity; i++) {
143    size_t slot;
144    const size_t kSliceCount = 1;
145    const int ret = producer_queue->AllocateBuffer(width, height, format, usage,
146                                                   kSliceCount, &slot);
147    if (ret < 0) {
148      ALOGE(
149          "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
150          producer_queue->id(), strerror(-ret));
151      return ErrorStatus(ENOMEM);
152    }
153    ALOGD_IF(
154        TRACE,
155        "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
156        slot, capacity);
157  }
158
159  return {std::move(producer_queue)};
160}
161
162DisplayClient::DisplayClient(int* error)
163    : BASE(pdx::default_transport::ClientChannelFactory::Create(
164               DisplayProtocol::kClientPath),
165           kInfiniteTimeout) {
166  if (error)
167    *error = Client::error();
168}
169
170Status<Metrics> DisplayClient::GetDisplayMetrics() {
171  return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
172}
173
174Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
175    const SurfaceAttributes& attributes) {
176  int error;
177  if (auto client = Surface::Create(attributes, &error))
178    return {std::move(client)};
179  else
180    return ErrorStatus(error);
181}
182
183Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
184    const std::string& name) {
185  auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
186  if (!status) {
187    ALOGE(
188        "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
189        "error=%s",
190        name.c_str(), status.GetErrorMessage().c_str());
191    return status.error_status();
192  }
193
194  auto ion_buffer = std::make_unique<IonBuffer>();
195  auto native_buffer_handle = status.take();
196  const int ret = native_buffer_handle.Import(ion_buffer.get());
197  if (ret < 0) {
198    ALOGE(
199        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
200        "name=%s; error=%s",
201        name.c_str(), strerror(-ret));
202    return ErrorStatus(-ret);
203  }
204
205  return {std::move(ion_buffer)};
206}
207
208Status<bool> DisplayClient::IsVrAppRunning() {
209  return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
210}
211
212}  // namespace display
213}  // namespace dvr
214}  // namespace android
215