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