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
14 using android::pdx::ErrorStatus;
15 using android::pdx::LocalHandle;
16 using android::pdx::LocalChannelHandle;
17 using android::pdx::Status;
18 using android::pdx::Transaction;
19 using android::pdx::rpc::IfAnyOf;
20
21 namespace android {
22 namespace dvr {
23 namespace display {
24
Surface(LocalChannelHandle channel_handle,int * error)25 Surface::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
Surface(const SurfaceAttributes & attributes,int * error)42 Surface::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
SetVisible(bool visible)60 Status<void> Surface::SetVisible(bool visible) {
61 return SetAttributes(
62 {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
63 }
64
SetZOrder(int z_order)65 Status<void> Surface::SetZOrder(int z_order) {
66 return SetAttributes(
67 {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
68 }
69
SetAttributes(const SurfaceAttributes & attributes)70 Status<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
CreateQueue(uint32_t width,uint32_t height,uint32_t format,size_t metadata_size)107 Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
108 uint32_t width, uint32_t height, uint32_t format, size_t metadata_size) {
109 ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
110 auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(
111 ProducerQueueConfigBuilder()
112 .SetDefaultWidth(width)
113 .SetDefaultHeight(height)
114 .SetDefaultFormat(format)
115 .SetMetadataSize(metadata_size)
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
CreateQueue(uint32_t width,uint32_t height,uint32_t layer_count,uint32_t format,uint64_t usage,size_t capacity,size_t metadata_size)132 Status<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, size_t metadata_size) {
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, metadata_size);
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 auto allocate_status = producer_queue->AllocateBuffers(
147 width, height, layer_count, format, usage, capacity);
148 if (!allocate_status) {
149 ALOGE("Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
150 producer_queue->id(), allocate_status.GetErrorMessage().c_str());
151 return allocate_status.error_status();
152 }
153
154 return {std::move(producer_queue)};
155 }
156
DisplayClient(int * error)157 DisplayClient::DisplayClient(int* error)
158 : BASE(pdx::default_transport::ClientChannelFactory::Create(
159 DisplayProtocol::kClientPath),
160 kInfiniteTimeout) {
161 if (error)
162 *error = Client::error();
163 }
164
GetDisplayMetrics()165 Status<Metrics> DisplayClient::GetDisplayMetrics() {
166 return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
167 }
168
GetConfigurationData(ConfigFileType config_type)169 Status<std::string> DisplayClient::GetConfigurationData(
170 ConfigFileType config_type) {
171 auto status =
172 InvokeRemoteMethod<DisplayProtocol::GetConfigurationData>(config_type);
173 if (!status && status.error() != ENOENT) {
174 ALOGE(
175 "DisplayClient::GetConfigurationData: Unable to get"
176 "configuration data. Error: %s",
177 status.GetErrorMessage().c_str());
178 }
179 return status;
180 }
181
CreateSurface(const SurfaceAttributes & attributes)182 Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
183 const SurfaceAttributes& attributes) {
184 int error;
185 if (auto client = Surface::Create(attributes, &error))
186 return {std::move(client)};
187 else
188 return ErrorStatus(error);
189 }
190
SetupGlobalBuffer(DvrGlobalBufferKey key,size_t size,uint64_t usage)191 pdx::Status<std::unique_ptr<IonBuffer>> DisplayClient::SetupGlobalBuffer(
192 DvrGlobalBufferKey key, size_t size, uint64_t usage) {
193 auto status =
194 InvokeRemoteMethod<DisplayProtocol::SetupGlobalBuffer>(key, size, usage);
195 if (!status) {
196 ALOGE(
197 "DisplayClient::SetupGlobalBuffer: Failed to create the global buffer "
198 "%s",
199 status.GetErrorMessage().c_str());
200 return status.error_status();
201 }
202
203 auto ion_buffer = std::make_unique<IonBuffer>();
204 auto native_buffer_handle = status.take();
205 const int ret = native_buffer_handle.Import(ion_buffer.get());
206 if (ret < 0) {
207 ALOGE(
208 "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
209 "key=%d; error=%s",
210 key, strerror(-ret));
211 return ErrorStatus(-ret);
212 }
213
214 return {std::move(ion_buffer)};
215 }
216
DeleteGlobalBuffer(DvrGlobalBufferKey key)217 pdx::Status<void> DisplayClient::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
218 auto status = InvokeRemoteMethod<DisplayProtocol::DeleteGlobalBuffer>(key);
219 if (!status) {
220 ALOGE("DisplayClient::DeleteGlobalBuffer Failed: %s",
221 status.GetErrorMessage().c_str());
222 }
223
224 return status;
225 }
226
GetGlobalBuffer(DvrGlobalBufferKey key)227 Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
228 DvrGlobalBufferKey key) {
229 auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
230 if (!status) {
231 ALOGE(
232 "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
233 "error=%s",
234 key, status.GetErrorMessage().c_str());
235 return status.error_status();
236 }
237
238 auto ion_buffer = std::make_unique<IonBuffer>();
239 auto native_buffer_handle = status.take();
240 const int ret = native_buffer_handle.Import(ion_buffer.get());
241 if (ret < 0) {
242 ALOGE(
243 "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
244 "key=%d; error=%s",
245 key, strerror(-ret));
246 return ErrorStatus(-ret);
247 }
248
249 return {std::move(ion_buffer)};
250 }
251
IsVrAppRunning()252 Status<bool> DisplayClient::IsVrAppRunning() {
253 return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
254 }
255
256 } // namespace display
257 } // namespace dvr
258 } // namespace android
259