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 
13 using android::pdx::ErrorStatus;
14 using android::pdx::LocalHandle;
15 using android::pdx::LocalChannelHandle;
16 using android::pdx::Status;
17 using android::pdx::Transaction;
18 using android::pdx::rpc::IfAnyOf;
19 
20 namespace android {
21 namespace dvr {
22 namespace display {
23 
Surface(LocalChannelHandle channel_handle,int * error)24 Surface::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 
Surface(const SurfaceAttributes & attributes,int * error)41 Surface::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 
SetVisible(bool visible)59 Status<void> Surface::SetVisible(bool visible) {
60   return SetAttributes(
61       {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
62 }
63 
SetZOrder(int z_order)64 Status<void> Surface::SetZOrder(int z_order) {
65   return SetAttributes(
66       {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
67 }
68 
SetAttributes(const SurfaceAttributes & attributes)69 Status<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 
CreateQueue(uint32_t width,uint32_t height,uint32_t format,size_t metadata_size)106 Status<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 
CreateQueue(uint32_t width,uint32_t height,uint32_t layer_count,uint32_t format,uint64_t usage,size_t capacity,size_t metadata_size)131 Status<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 
DisplayClient(int * error)156 DisplayClient::DisplayClient(int* error)
157     : BASE(pdx::default_transport::ClientChannelFactory::Create(
158                DisplayProtocol::kClientPath),
159            kInfiniteTimeout) {
160   if (error)
161     *error = Client::error();
162 }
163 
GetDisplayMetrics()164 Status<Metrics> DisplayClient::GetDisplayMetrics() {
165   return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
166 }
167 
GetConfigurationData(ConfigFileType config_type)168 Status<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 
GetDisplayIdentificationPort()181 Status<uint8_t> DisplayClient::GetDisplayIdentificationPort() {
182   return InvokeRemoteMethod<DisplayProtocol::GetDisplayIdentificationPort>();
183 }
184 
CreateSurface(const SurfaceAttributes & attributes)185 Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
186     const SurfaceAttributes& attributes) {
187   int error;
188   if (auto client = Surface::Create(attributes, &error))
189     return {std::move(client)};
190   else
191     return ErrorStatus(error);
192 }
193 
SetupGlobalBuffer(DvrGlobalBufferKey key,size_t size,uint64_t usage)194 pdx::Status<std::unique_ptr<IonBuffer>> DisplayClient::SetupGlobalBuffer(
195     DvrGlobalBufferKey key, size_t size, uint64_t usage) {
196   auto status =
197       InvokeRemoteMethod<DisplayProtocol::SetupGlobalBuffer>(key, size, usage);
198   if (!status) {
199     ALOGE(
200         "DisplayClient::SetupGlobalBuffer: Failed to create the global buffer "
201         "%s",
202         status.GetErrorMessage().c_str());
203     return status.error_status();
204   }
205 
206   auto ion_buffer = std::make_unique<IonBuffer>();
207   auto native_buffer_handle = status.take();
208   const int ret = native_buffer_handle.Import(ion_buffer.get());
209   if (ret < 0) {
210     ALOGE(
211         "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
212         "key=%d; error=%s",
213         key, strerror(-ret));
214     return ErrorStatus(-ret);
215   }
216 
217   return {std::move(ion_buffer)};
218 }
219 
DeleteGlobalBuffer(DvrGlobalBufferKey key)220 pdx::Status<void> DisplayClient::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
221   auto status = InvokeRemoteMethod<DisplayProtocol::DeleteGlobalBuffer>(key);
222   if (!status) {
223     ALOGE("DisplayClient::DeleteGlobalBuffer Failed: %s",
224           status.GetErrorMessage().c_str());
225   }
226 
227   return status;
228 }
229 
GetGlobalBuffer(DvrGlobalBufferKey key)230 Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
231     DvrGlobalBufferKey key) {
232   auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
233   if (!status) {
234     ALOGE(
235         "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
236         "error=%s",
237         key, status.GetErrorMessage().c_str());
238     return status.error_status();
239   }
240 
241   auto ion_buffer = std::make_unique<IonBuffer>();
242   auto native_buffer_handle = status.take();
243   const int ret = native_buffer_handle.Import(ion_buffer.get());
244   if (ret < 0) {
245     ALOGE(
246         "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
247         "key=%d; error=%s",
248         key, strerror(-ret));
249     return ErrorStatus(-ret);
250   }
251 
252   return {std::move(ion_buffer)};
253 }
254 
IsVrAppRunning()255 Status<bool> DisplayClient::IsVrAppRunning() {
256   return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
257 }
258 
259 }  // namespace display
260 }  // namespace dvr
261 }  // namespace android
262