blob: 442c82d17f5ea3346f842a69b9bbcebb648fba27 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "include/private/dvr/display_client.h"
2
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08003#include <cutils/native_handle.h>
Alex Vakulenko4fe60582017-02-02 11:35:59 -08004#include <log/log.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08005#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
Corey Tabaka3f82d312017-04-20 14:42:08 -070011#include <private/dvr/display_protocol.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080012#include <private/dvr/native_buffer.h>
13
Corey Tabaka2251d822017-04-20 16:04:07 -070014using android::pdx::ErrorStatus;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080015using 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 {
Corey Tabaka2251d822017-04-20 16:04:07 -070023namespace display {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080024
Corey Tabaka2251d822017-04-20 16:04:07 -070025Surface::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",
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080031 status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080032 Close(status.error());
Corey Tabaka2251d822017-04-20 16:04:07 -070033 if (error)
34 *error = status.error();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080035 }
Corey Tabaka2251d822017-04-20 16:04:07 -070036
37 surface_id_ = status.get().surface_id;
38 z_order_ = status.get().z_order;
39 visible_ = status.get().visible;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080040}
41
Corey Tabaka2251d822017-04-20 16:04:07 -070042Surface::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;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080058}
59
Corey Tabaka2251d822017-04-20 16:04:07 -070060Status<void> Surface::SetVisible(bool visible) {
61 return SetAttributes(
62 {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080063}
64
Corey Tabaka2251d822017-04-20 16:04:07 -070065Status<void> Surface::SetZOrder(int z_order) {
66 return SetAttributes(
67 {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080068}
69
Corey Tabaka2251d822017-04-20 16:04:07 -070070Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
71 auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080072 if (!status) {
73 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -070074 "Surface::SetAttributes: Failed to set display surface "
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080075 "attributes: %s",
76 status.GetErrorMessage().c_str());
Corey Tabaka2251d822017-04-20 16:04:07 -070077 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080078 }
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) {
Corey Tabaka2251d822017-04-20 16:04:07 -070087 case SurfaceAttribute::Visible:
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080088 invalid_value =
89 !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
90 break;
Corey Tabaka2251d822017-04-20 16:04:07 -070091 case SurfaceAttribute::ZOrder:
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080092 invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
93 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080094 }
95
96 if (invalid_value) {
97 ALOGW(
Corey Tabaka2251d822017-04-20 16:04:07 -070098 "Surface::SetAttributes: Failed to set display surface "
99 "attribute %d because of incompatible type: %d",
100 key, variant->index());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800101 }
102 }
103
Corey Tabaka2251d822017-04-20 16:04:07 -0700104 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800105}
106
Corey Tabaka99c2d732017-06-07 17:54:33 -0700107Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
108 uint32_t width, uint32_t height, uint32_t format, size_t metadata_size) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700109 ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700110 auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(
111 ProducerQueueConfigBuilder()
112 .SetDefaultWidth(width)
113 .SetDefaultHeight(height)
114 .SetDefaultFormat(format)
Jiwen 'Steve' Cai532e5292017-06-02 15:36:44 -0700115 .SetMetadataSize(metadata_size)
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700116 .Build());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800117 if (!status) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700118 ALOGE("Surface::CreateQueue: Failed to create queue: %s",
119 status.GetErrorMessage().c_str());
120 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800121 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700122
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
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700132Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
133 uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
Jiwen 'Steve' Cai532e5292017-06-02 15:36:44 -0700134 uint64_t usage, size_t capacity, size_t metadata_size) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700135 ALOGD_IF(TRACE,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700136 "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
137 "usage=%" PRIx64 " capacity=%zu",
138 width, height, layer_count, format, usage, capacity);
Jiwen 'Steve' Cai532e5292017-06-02 15:36:44 -0700139 auto status = CreateQueue(width, height, format, metadata_size);
Corey Tabaka2251d822017-04-20 16:04:07 -0700140 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);
Jiwen 'Steve' Cai8fa4e102017-05-24 23:16:54 -0700146 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",
Corey Tabakab7ca5de2017-05-08 18:55:02 -0700150 producer_queue->id(), allocate_status.GetErrorMessage().c_str());
Jiwen 'Steve' Cai8fa4e102017-05-24 23:16:54 -0700151 return allocate_status.error_status();
Corey Tabaka2251d822017-04-20 16:04:07 -0700152 }
153
154 return {std::move(producer_queue)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800155}
156
157DisplayClient::DisplayClient(int* error)
158 : BASE(pdx::default_transport::ClientChannelFactory::Create(
Corey Tabaka2251d822017-04-20 16:04:07 -0700159 DisplayProtocol::kClientPath),
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800160 kInfiniteTimeout) {
161 if (error)
162 *error = Client::error();
163}
164
Corey Tabaka2251d822017-04-20 16:04:07 -0700165Status<Metrics> DisplayClient::GetDisplayMetrics() {
166 return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800167}
168
Hendrik Wagenaarbcb03d02017-05-23 14:59:08 -0700169Status<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
Corey Tabaka2251d822017-04-20 16:04:07 -0700182Status<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);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800189}
190
Corey Tabaka99c2d732017-06-07 17:54:33 -0700191pdx::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
217pdx::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
Okan Arikan36d23802017-05-15 15:20:39 -0700227Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
228 DvrGlobalBufferKey key) {
229 auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700230 if (!status) {
231 ALOGE(
Okan Arikan36d23802017-05-15 15:20:39 -0700232 "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700233 "error=%s",
Okan Arikan36d23802017-05-15 15:20:39 -0700234 key, status.GetErrorMessage().c_str());
Corey Tabaka2251d822017-04-20 16:04:07 -0700235 return status.error_status();
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700236 }
237
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700238 auto ion_buffer = std::make_unique<IonBuffer>();
Corey Tabaka2251d822017-04-20 16:04:07 -0700239 auto native_buffer_handle = status.take();
240 const int ret = native_buffer_handle.Import(ion_buffer.get());
241 if (ret < 0) {
242 ALOGE(
Okan Arikan36d23802017-05-15 15:20:39 -0700243 "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
244 "key=%d; error=%s",
245 key, strerror(-ret));
Corey Tabaka2251d822017-04-20 16:04:07 -0700246 return ErrorStatus(-ret);
247 }
248
249 return {std::move(ion_buffer)};
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700250}
251
Corey Tabaka2251d822017-04-20 16:04:07 -0700252Status<bool> DisplayClient::IsVrAppRunning() {
253 return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
Albert Chaulkb7c8a4b2017-03-20 13:03:39 -0400254}
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700255
Corey Tabaka2251d822017-04-20 16:04:07 -0700256} // namespace display
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800257} // namespace dvr
258} // namespace android