blob: 5c9ebd41b61b28238377e1bb5cef2059eb5f164e [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/late_latch.h>
13#include <private/dvr/native_buffer.h>
14
Corey Tabaka2251d822017-04-20 16:04:07 -070015using android::pdx::ErrorStatus;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080016using android::pdx::LocalHandle;
17using android::pdx::LocalChannelHandle;
18using android::pdx::Status;
19using android::pdx::Transaction;
20using android::pdx::rpc::IfAnyOf;
21
22namespace android {
23namespace dvr {
Corey Tabaka2251d822017-04-20 16:04:07 -070024namespace display {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080025
Corey Tabaka2251d822017-04-20 16:04:07 -070026Surface::Surface(LocalChannelHandle channel_handle, int* error)
27 : BASE{pdx::default_transport::ClientChannel::Create(
28 std::move(channel_handle))} {
29 auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>();
30 if (!status) {
31 ALOGE("Surface::Surface: Failed to get surface info: %s",
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080032 status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080033 Close(status.error());
Corey Tabaka2251d822017-04-20 16:04:07 -070034 if (error)
35 *error = status.error();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080036 }
Corey Tabaka2251d822017-04-20 16:04:07 -070037
38 surface_id_ = status.get().surface_id;
39 z_order_ = status.get().z_order;
40 visible_ = status.get().visible;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080041}
42
Corey Tabaka2251d822017-04-20 16:04:07 -070043Surface::Surface(const SurfaceAttributes& attributes, int* error)
44 : BASE{pdx::default_transport::ClientChannelFactory::Create(
45 DisplayProtocol::kClientPath),
46 kInfiniteTimeout} {
47 auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes);
48 if (!status) {
49 ALOGE("Surface::Surface: Failed to create display surface: %s",
50 status.GetErrorMessage().c_str());
51 Close(status.error());
52 if (error)
53 *error = status.error();
54 }
55
56 surface_id_ = status.get().surface_id;
57 z_order_ = status.get().z_order;
58 visible_ = status.get().visible;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080059}
60
Corey Tabaka2251d822017-04-20 16:04:07 -070061Status<void> Surface::SetVisible(bool visible) {
62 return SetAttributes(
63 {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080064}
65
Corey Tabaka2251d822017-04-20 16:04:07 -070066Status<void> Surface::SetZOrder(int z_order) {
67 return SetAttributes(
68 {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080069}
70
Corey Tabaka2251d822017-04-20 16:04:07 -070071Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
72 auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080073 if (!status) {
74 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -070075 "Surface::SetAttributes: Failed to set display surface "
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080076 "attributes: %s",
77 status.GetErrorMessage().c_str());
Corey Tabaka2251d822017-04-20 16:04:07 -070078 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080079 }
80
81 // Set the local cached copies of the attributes we care about from the full
82 // set of attributes sent to the display service.
83 for (const auto& attribute : attributes) {
84 const auto& key = attribute.first;
85 const auto* variant = &attribute.second;
86 bool invalid_value = false;
87 switch (key) {
Corey Tabaka2251d822017-04-20 16:04:07 -070088 case SurfaceAttribute::Visible:
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080089 invalid_value =
90 !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
91 break;
Corey Tabaka2251d822017-04-20 16:04:07 -070092 case SurfaceAttribute::ZOrder:
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080093 invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
94 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080095 }
96
97 if (invalid_value) {
98 ALOGW(
Corey Tabaka2251d822017-04-20 16:04:07 -070099 "Surface::SetAttributes: Failed to set display surface "
100 "attribute %d because of incompatible type: %d",
101 key, variant->index());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800102 }
103 }
104
Corey Tabaka2251d822017-04-20 16:04:07 -0700105 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800106}
107
Corey Tabaka2251d822017-04-20 16:04:07 -0700108Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() {
109 ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
110 auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800111 if (!status) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700112 ALOGE("Surface::CreateQueue: Failed to create queue: %s",
113 status.GetErrorMessage().c_str());
114 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800115 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700116
117 auto producer_queue = ProducerQueue::Import(status.take());
118 if (!producer_queue) {
119 ALOGE("Surface::CreateQueue: Failed to import producer queue!");
120 return ErrorStatus(ENOMEM);
121 }
122
123 return {std::move(producer_queue)};
124}
125
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700126Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
127 uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
128 uint64_t usage, size_t capacity) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700129 ALOGD_IF(TRACE,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700130 "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
131 "usage=%" PRIx64 " capacity=%zu",
132 width, height, layer_count, format, usage, capacity);
Corey Tabaka2251d822017-04-20 16:04:07 -0700133 auto status = CreateQueue();
134 if (!status)
135 return status.error_status();
136
137 auto producer_queue = status.take();
138
139 ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
140 for (size_t i = 0; i < capacity; i++) {
141 size_t slot;
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700142 const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
143 format, usage, &slot);
Corey Tabaka2251d822017-04-20 16:04:07 -0700144 if (ret < 0) {
145 ALOGE(
146 "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
147 producer_queue->id(), strerror(-ret));
148 return ErrorStatus(ENOMEM);
149 }
150 ALOGD_IF(
151 TRACE,
152 "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
153 slot, capacity);
154 }
155
156 return {std::move(producer_queue)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800157}
158
159DisplayClient::DisplayClient(int* error)
160 : BASE(pdx::default_transport::ClientChannelFactory::Create(
Corey Tabaka2251d822017-04-20 16:04:07 -0700161 DisplayProtocol::kClientPath),
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800162 kInfiniteTimeout) {
163 if (error)
164 *error = Client::error();
165}
166
Corey Tabaka2251d822017-04-20 16:04:07 -0700167Status<Metrics> DisplayClient::GetDisplayMetrics() {
168 return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800169}
170
Corey Tabaka2251d822017-04-20 16:04:07 -0700171Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
172 const SurfaceAttributes& attributes) {
173 int error;
174 if (auto client = Surface::Create(attributes, &error))
175 return {std::move(client)};
176 else
177 return ErrorStatus(error);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800178}
179
Corey Tabaka2251d822017-04-20 16:04:07 -0700180Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700181 const std::string& name) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700182 auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700183 if (!status) {
184 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700185 "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700186 "error=%s",
187 name.c_str(), status.GetErrorMessage().c_str());
Corey Tabaka2251d822017-04-20 16:04:07 -0700188 return status.error_status();
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700189 }
190
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700191 auto ion_buffer = std::make_unique<IonBuffer>();
Corey Tabaka2251d822017-04-20 16:04:07 -0700192 auto native_buffer_handle = status.take();
193 const int ret = native_buffer_handle.Import(ion_buffer.get());
194 if (ret < 0) {
195 ALOGE(
196 "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
197 "name=%s; error=%s",
198 name.c_str(), strerror(-ret));
199 return ErrorStatus(-ret);
200 }
201
202 return {std::move(ion_buffer)};
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700203}
204
Corey Tabaka2251d822017-04-20 16:04:07 -0700205Status<bool> DisplayClient::IsVrAppRunning() {
206 return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
Albert Chaulkb7c8a4b2017-03-20 13:03:39 -0400207}
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700208
Corey Tabaka2251d822017-04-20 16:04:07 -0700209} // namespace display
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800210} // namespace dvr
211} // namespace android