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()107 Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() {
108 ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
109 auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0);
110 if (!status) {
111 ALOGE("Surface::CreateQueue: Failed to create queue: %s",
112 status.GetErrorMessage().c_str());
113 return status.error_status();
114 }
115
116 auto producer_queue = ProducerQueue::Import(status.take());
117 if (!producer_queue) {
118 ALOGE("Surface::CreateQueue: Failed to import producer queue!");
119 return ErrorStatus(ENOMEM);
120 }
121
122 return {std::move(producer_queue)};
123 }
124
CreateQueue(uint32_t width,uint32_t height,uint32_t layer_count,uint32_t format,uint64_t usage,size_t capacity)125 Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
126 uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
127 uint64_t usage, size_t capacity) {
128 ALOGD_IF(TRACE,
129 "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
130 "usage=%" PRIx64 " capacity=%zu",
131 width, height, layer_count, format, usage, capacity);
132 auto status = CreateQueue();
133 if (!status)
134 return status.error_status();
135
136 auto producer_queue = status.take();
137
138 ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
139 for (size_t i = 0; i < capacity; i++) {
140 size_t slot;
141 const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
142 format, usage, &slot);
143 if (ret < 0) {
144 ALOGE(
145 "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
146 producer_queue->id(), strerror(-ret));
147 return ErrorStatus(ENOMEM);
148 }
149 ALOGD_IF(
150 TRACE,
151 "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
152 slot, capacity);
153 }
154
155 return {std::move(producer_queue)};
156 }
157
DisplayClient(int * error)158 DisplayClient::DisplayClient(int* error)
159 : BASE(pdx::default_transport::ClientChannelFactory::Create(
160 DisplayProtocol::kClientPath),
161 kInfiniteTimeout) {
162 if (error)
163 *error = Client::error();
164 }
165
GetDisplayMetrics()166 Status<Metrics> DisplayClient::GetDisplayMetrics() {
167 return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
168 }
169
CreateSurface(const SurfaceAttributes & attributes)170 Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
171 const SurfaceAttributes& attributes) {
172 int error;
173 if (auto client = Surface::Create(attributes, &error))
174 return {std::move(client)};
175 else
176 return ErrorStatus(error);
177 }
178
GetNamedBuffer(const std::string & name)179 Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
180 const std::string& name) {
181 auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
182 if (!status) {
183 ALOGE(
184 "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
185 "error=%s",
186 name.c_str(), status.GetErrorMessage().c_str());
187 return status.error_status();
188 }
189
190 auto ion_buffer = std::make_unique<IonBuffer>();
191 auto native_buffer_handle = status.take();
192 const int ret = native_buffer_handle.Import(ion_buffer.get());
193 if (ret < 0) {
194 ALOGE(
195 "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
196 "name=%s; error=%s",
197 name.c_str(), strerror(-ret));
198 return ErrorStatus(-ret);
199 }
200
201 return {std::move(ion_buffer)};
202 }
203
IsVrAppRunning()204 Status<bool> DisplayClient::IsVrAppRunning() {
205 return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
206 }
207
208 } // namespace display
209 } // namespace dvr
210 } // namespace android
211