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 
CreateSurface(const SurfaceAttributes & attributes)181 Status<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 
SetupGlobalBuffer(DvrGlobalBufferKey key,size_t size,uint64_t usage)190 pdx::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 
DeleteGlobalBuffer(DvrGlobalBufferKey key)216 pdx::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 
GetGlobalBuffer(DvrGlobalBufferKey key)226 Status<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 
IsVrAppRunning()251 Status<bool> DisplayClient::IsVrAppRunning() {
252   return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
253 }
254 
255 }  // namespace display
256 }  // namespace dvr
257 }  // namespace android
258