display_client.cpp revision 656f406fcb0c45fd3c729a513bdd3f353cc6ec1f
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::unique_ptr<Surface>> DisplayClient::CreateSurface(
178    const SurfaceAttributes& attributes) {
179  int error;
180  if (auto client = Surface::Create(attributes, &error))
181    return {std::move(client)};
182  else
183    return ErrorStatus(error);
184}
185
186Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
187    DvrGlobalBufferKey key) {
188  auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
189  if (!status) {
190    ALOGE(
191        "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
192        "error=%s",
193        key, status.GetErrorMessage().c_str());
194    return status.error_status();
195  }
196
197  auto ion_buffer = std::make_unique<IonBuffer>();
198  auto native_buffer_handle = status.take();
199  const int ret = native_buffer_handle.Import(ion_buffer.get());
200  if (ret < 0) {
201    ALOGE(
202        "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
203        "key=%d; error=%s",
204        key, strerror(-ret));
205    return ErrorStatus(-ret);
206  }
207
208  return {std::move(ion_buffer)};
209}
210
211Status<bool> DisplayClient::IsVrAppRunning() {
212  return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
213}
214
215}  // namespace display
216}  // namespace dvr
217}  // namespace android
218