display_client.cpp revision 3c3f4314efbf7578fcd90d36dbe4111d72ce44cc
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(uint32_t width,
108                                                            uint32_t height,
109                                                            uint32_t format) {
110  ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
111  auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(
112      ProducerQueueConfigBuilder()
113          .SetDefaultWidth(width)
114          .SetDefaultHeight(height)
115          .SetDefaultFormat(format)
116          .Build());
117  if (!status) {
118    ALOGE("Surface::CreateQueue: Failed to create queue: %s",
119          status.GetErrorMessage().c_str());
120    return status.error_status();
121  }
122
123  auto producer_queue = ProducerQueue::Import(status.take());
124  if (!producer_queue) {
125    ALOGE("Surface::CreateQueue: Failed to import producer queue!");
126    return ErrorStatus(ENOMEM);
127  }
128
129  return {std::move(producer_queue)};
130}
131
132Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
133    uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
134    uint64_t usage, size_t capacity) {
135  ALOGD_IF(TRACE,
136           "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
137           "usage=%" PRIx64 " capacity=%zu",
138           width, height, layer_count, format, usage, capacity);
139  auto status = CreateQueue(width, height, format);
140  if (!status)
141    return status.error_status();
142
143  auto producer_queue = status.take();
144
145  ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
146  for (size_t i = 0; i < capacity; i++) {
147    size_t slot;
148    auto allocate_status = producer_queue->AllocateBuffer(
149        width, height, layer_count, format, usage, &slot);
150    if (!allocate_status) {
151      ALOGE(
152          "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
153          producer_queue->id(), allocate_status.GetErrorMessage().c_str());
154      return allocate_status.error_status();
155    }
156    ALOGD_IF(
157        TRACE,
158        "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
159        slot, capacity);
160  }
161
162  return {std::move(producer_queue)};
163}
164
165DisplayClient::DisplayClient(int* error)
166    : BASE(pdx::default_transport::ClientChannelFactory::Create(
167               DisplayProtocol::kClientPath),
168           kInfiniteTimeout) {
169  if (error)
170    *error = Client::error();
171}
172
173Status<Metrics> DisplayClient::GetDisplayMetrics() {
174  return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
175}
176
177Status<std::string> DisplayClient::GetConfigurationData(
178    ConfigFileType config_type) {
179  auto status =
180      InvokeRemoteMethod<DisplayProtocol::GetConfigurationData>(config_type);
181  if (!status && status.error() != ENOENT) {
182    ALOGE(
183        "DisplayClient::GetConfigurationData: Unable to get"
184        "configuration data. Error: %s",
185        status.GetErrorMessage().c_str());
186  }
187  return status;
188}
189
190Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
191    const SurfaceAttributes& attributes) {
192  int error;
193  if (auto client = Surface::Create(attributes, &error))
194    return {std::move(client)};
195  else
196    return ErrorStatus(error);
197}
198
199Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
200    DvrGlobalBufferKey key) {
201  auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
202  if (!status) {
203    ALOGE(
204        "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
205        "error=%s",
206        key, status.GetErrorMessage().c_str());
207    return status.error_status();
208  }
209
210  auto ion_buffer = std::make_unique<IonBuffer>();
211  auto native_buffer_handle = status.take();
212  const int ret = native_buffer_handle.Import(ion_buffer.get());
213  if (ret < 0) {
214    ALOGE(
215        "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
216        "key=%d; error=%s",
217        key, strerror(-ret));
218    return ErrorStatus(-ret);
219  }
220
221  return {std::move(ion_buffer)};
222}
223
224Status<bool> DisplayClient::IsVrAppRunning() {
225  return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
226}
227
228}  // namespace display
229}  // namespace dvr
230}  // namespace android
231