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
13using android::pdx::ErrorStatus;
14using android::pdx::LocalHandle;
15using android::pdx::LocalChannelHandle;
16using android::pdx::Status;
17using android::pdx::Transaction;
18using android::pdx::rpc::IfAnyOf;
19
20namespace android {
21namespace dvr {
22namespace display {
23
24Surface::Surface(LocalChannelHandle channel_handle, int* error)
25    : BASE{pdx::default_transport::ClientChannel::Create(
26          std::move(channel_handle))} {
27  auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>();
28  if (!status) {
29    ALOGE("Surface::Surface: Failed to get surface info: %s",
30          status.GetErrorMessage().c_str());
31    Close(status.error());
32    if (error)
33      *error = status.error();
34  }
35
36  surface_id_ = status.get().surface_id;
37  z_order_ = status.get().z_order;
38  visible_ = status.get().visible;
39}
40
41Surface::Surface(const SurfaceAttributes& attributes, int* error)
42    : BASE{pdx::default_transport::ClientChannelFactory::Create(
43               DisplayProtocol::kClientPath),
44           kInfiniteTimeout} {
45  auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes);
46  if (!status) {
47    ALOGE("Surface::Surface: Failed to create display surface: %s",
48          status.GetErrorMessage().c_str());
49    Close(status.error());
50    if (error)
51      *error = status.error();
52  }
53
54  surface_id_ = status.get().surface_id;
55  z_order_ = status.get().z_order;
56  visible_ = status.get().visible;
57}
58
59Status<void> Surface::SetVisible(bool visible) {
60  return SetAttributes(
61      {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
62}
63
64Status<void> Surface::SetZOrder(int z_order) {
65  return SetAttributes(
66      {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
67}
68
69Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
70  auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
71  if (!status) {
72    ALOGE(
73        "Surface::SetAttributes: Failed to set display surface "
74        "attributes: %s",
75        status.GetErrorMessage().c_str());
76    return status.error_status();
77  }
78
79  // Set the local cached copies of the attributes we care about from the full
80  // set of attributes sent to the display service.
81  for (const auto& attribute : attributes) {
82    const auto& key = attribute.first;
83    const auto* variant = &attribute.second;
84    bool invalid_value = false;
85    switch (key) {
86      case SurfaceAttribute::Visible:
87        invalid_value =
88            !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
89        break;
90      case SurfaceAttribute::ZOrder:
91        invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
92        break;
93    }
94
95    if (invalid_value) {
96      ALOGW(
97          "Surface::SetAttributes: Failed to set display surface "
98          "attribute %d because of incompatible type: %d",
99          key, variant->index());
100    }
101  }
102
103  return {};
104}
105
106Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
107    uint32_t width, uint32_t height, uint32_t format, size_t metadata_size) {
108  ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
109  auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(
110      ProducerQueueConfigBuilder()
111          .SetDefaultWidth(width)
112          .SetDefaultHeight(height)
113          .SetDefaultFormat(format)
114          .SetMetadataSize(metadata_size)
115          .Build());
116  if (!status) {
117    ALOGE("Surface::CreateQueue: Failed to create queue: %s",
118          status.GetErrorMessage().c_str());
119    return status.error_status();
120  }
121
122  auto producer_queue = ProducerQueue::Import(status.take());
123  if (!producer_queue) {
124    ALOGE("Surface::CreateQueue: Failed to import producer queue!");
125    return ErrorStatus(ENOMEM);
126  }
127
128  return {std::move(producer_queue)};
129}
130
131Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
132    uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
133    uint64_t usage, size_t capacity, size_t metadata_size) {
134  ALOGD_IF(TRACE,
135           "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
136           "usage=%" PRIx64 " capacity=%zu",
137           width, height, layer_count, format, usage, capacity);
138  auto status = CreateQueue(width, height, format, metadata_size);
139  if (!status)
140    return status.error_status();
141
142  auto producer_queue = status.take();
143
144  ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
145  auto allocate_status = producer_queue->AllocateBuffers(
146      width, height, layer_count, format, usage, capacity);
147  if (!allocate_status) {
148    ALOGE("Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
149          producer_queue->id(), allocate_status.GetErrorMessage().c_str());
150    return allocate_status.error_status();
151  }
152
153  return {std::move(producer_queue)};
154}
155
156DisplayClient::DisplayClient(int* error)
157    : BASE(pdx::default_transport::ClientChannelFactory::Create(
158               DisplayProtocol::kClientPath),
159           kInfiniteTimeout) {
160  if (error)
161    *error = Client::error();
162}
163
164Status<Metrics> DisplayClient::GetDisplayMetrics() {
165  return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
166}
167
168Status<std::string> DisplayClient::GetConfigurationData(
169    ConfigFileType config_type) {
170  auto status =
171      InvokeRemoteMethod<DisplayProtocol::GetConfigurationData>(config_type);
172  if (!status && status.error() != ENOENT) {
173    ALOGE(
174        "DisplayClient::GetConfigurationData: Unable to get"
175        "configuration data. Error: %s",
176        status.GetErrorMessage().c_str());
177  }
178  return status;
179}
180
181Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
182    const SurfaceAttributes& attributes) {
183  int error;
184  if (auto client = Surface::Create(attributes, &error))
185    return {std::move(client)};
186  else
187    return ErrorStatus(error);
188}
189
190pdx::Status<std::unique_ptr<IonBuffer>> DisplayClient::SetupGlobalBuffer(
191    DvrGlobalBufferKey key, size_t size, uint64_t usage) {
192  auto status =
193      InvokeRemoteMethod<DisplayProtocol::SetupGlobalBuffer>(key, size, usage);
194  if (!status) {
195    ALOGE(
196        "DisplayClient::SetupGlobalBuffer: Failed to create the global buffer "
197        "%s",
198        status.GetErrorMessage().c_str());
199    return status.error_status();
200  }
201
202  auto ion_buffer = std::make_unique<IonBuffer>();
203  auto native_buffer_handle = status.take();
204  const int ret = native_buffer_handle.Import(ion_buffer.get());
205  if (ret < 0) {
206    ALOGE(
207        "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
208        "key=%d; error=%s",
209        key, strerror(-ret));
210    return ErrorStatus(-ret);
211  }
212
213  return {std::move(ion_buffer)};
214}
215
216pdx::Status<void> DisplayClient::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
217  auto status = InvokeRemoteMethod<DisplayProtocol::DeleteGlobalBuffer>(key);
218  if (!status) {
219    ALOGE("DisplayClient::DeleteGlobalBuffer Failed: %s",
220          status.GetErrorMessage().c_str());
221  }
222
223  return status;
224}
225
226Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
227    DvrGlobalBufferKey key) {
228  auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
229  if (!status) {
230    ALOGE(
231        "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
232        "error=%s",
233        key, status.GetErrorMessage().c_str());
234    return status.error_status();
235  }
236
237  auto ion_buffer = std::make_unique<IonBuffer>();
238  auto native_buffer_handle = status.take();
239  const int ret = native_buffer_handle.Import(ion_buffer.get());
240  if (ret < 0) {
241    ALOGE(
242        "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
243        "key=%d; error=%s",
244        key, strerror(-ret));
245    return ErrorStatus(-ret);
246  }
247
248  return {std::move(ion_buffer)};
249}
250
251Status<bool> DisplayClient::IsVrAppRunning() {
252  return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
253}
254
255}  // namespace display
256}  // namespace dvr
257}  // namespace android
258