1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "H2BGraphicBufferProducer@2.0"
19
20 #include <android-base/logging.h>
21
22 #include <android/hardware/graphics/common/1.2/types.h>
23 #include <gui/bufferqueue/2.0/B2HProducerListener.h>
24 #include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
25 #include <gui/bufferqueue/2.0/types.h>
26 #include <ui/GraphicBuffer.h>
27 #include <ui/Rect.h>
28 #include <ui/Region.h>
29 #include <vndk/hardware_buffer.h>
30
31 namespace android {
32 namespace hardware {
33 namespace graphics {
34 namespace bufferqueue {
35 namespace V2_0 {
36 namespace utils {
37
38 namespace /* unnamed */ {
39
40 using BQueueBufferInput = ::android::
41 IGraphicBufferProducer::QueueBufferInput;
42 using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0::
43 IGraphicBufferProducer::QueueBufferInput;
44 using BQueueBufferOutput = ::android::
45 IGraphicBufferProducer::QueueBufferOutput;
46 using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0::
47 IGraphicBufferProducer::QueueBufferOutput;
48
49 using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
50 using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
51
b2h(BQueueBufferInput const & from,HQueueBufferInput * to,HFenceWrapper * hFenceWrapper)52 bool b2h(BQueueBufferInput const& from, HQueueBufferInput* to,
53 HFenceWrapper* hFenceWrapper) {
54 to->timestamp = from.timestamp;
55 to->isAutoTimestamp = static_cast<bool>(from.isAutoTimestamp);
56 to->dataSpace = static_cast<int32_t>(from.dataSpace);
57 to->transform = static_cast<int32_t>(from.transform);
58 to->stickyTransform = static_cast<int32_t>(from.stickyTransform);
59 if (!b2h(from.crop, &to->crop) ||
60 !b2h(from.surfaceDamage, &to->surfaceDamage) ||
61 !b2h(from.fence, hFenceWrapper)) {
62 return false;
63 }
64 to->fence = hFenceWrapper->getHandle();
65 return true;
66 }
67
h2b(HQueueBufferOutput const & from,BQueueBufferOutput * to)68 bool h2b(HQueueBufferOutput const& from, BQueueBufferOutput* to) {
69 to->width = from.width;
70 to->height = from.height;
71 to->transformHint = static_cast<uint32_t>(from.transformHint);
72 to->numPendingBuffers = from.numPendingBuffers;
73 to->nextFrameNumber = from.nextFrameNumber;
74 to->bufferReplaced = from.bufferReplaced;
75 return true;
76 }
77
78 } // unnamed namespace
79
80 // H2BGraphicBufferProducer
81 // ========================
82
requestBuffer(int slot,sp<GraphicBuffer> * bBuffer)83 status_t H2BGraphicBufferProducer::requestBuffer(int slot,
84 sp<GraphicBuffer>* bBuffer) {
85 bool converted{};
86 status_t bStatus{};
87 Return<void> transResult = mBase->requestBuffer(slot,
88 [&converted, &bStatus, bBuffer](
89 HStatus hStatus,
90 HardwareBuffer const& hBuffer,
91 uint32_t generationNumber) {
92 converted =
93 h2b(hStatus, &bStatus) &&
94 h2b(hBuffer, bBuffer);
95 if (*bBuffer) {
96 (*bBuffer)->setGenerationNumber(generationNumber);
97 }
98 });
99 if (!transResult.isOk()) {
100 LOG(ERROR) << "requestBuffer: transaction failed.";
101 return FAILED_TRANSACTION;
102 }
103 if (!converted) {
104 LOG(ERROR) << "requestBuffer: corrupted transaction.";
105 return FAILED_TRANSACTION;
106 }
107 return bStatus;
108 }
109
setMaxDequeuedBufferCount(int maxDequeuedBuffers)110 status_t H2BGraphicBufferProducer::setMaxDequeuedBufferCount(
111 int maxDequeuedBuffers) {
112 status_t bStatus{};
113 Return<HStatus> transResult = mBase->setMaxDequeuedBufferCount(
114 static_cast<int32_t>(maxDequeuedBuffers));
115 if (!transResult.isOk()) {
116 LOG(ERROR) << "setMaxDequeuedBufferCount: transaction failed.";
117 return FAILED_TRANSACTION;
118 }
119 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
120 LOG(ERROR) << "setMaxDequeuedBufferCount: corrupted transaction.";
121 return FAILED_TRANSACTION;
122 }
123 return bStatus;
124 }
125
setAsyncMode(bool async)126 status_t H2BGraphicBufferProducer::setAsyncMode(bool async) {
127 status_t bStatus{};
128 Return<HStatus> transResult = mBase->setAsyncMode(async);
129 if (!transResult.isOk()) {
130 LOG(ERROR) << "setAsyncMode: transaction failed.";
131 return FAILED_TRANSACTION;
132 }
133 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
134 LOG(ERROR) << "setAsyncMode: corrupted transaction.";
135 return FAILED_TRANSACTION;
136 }
137 return bStatus;
138 }
139
dequeueBuffer(int * slot,sp<BFence> * fence,uint32_t w,uint32_t h,PixelFormat format,uint64_t usage,uint64_t * outBufferAge,FrameEventHistoryDelta *)140 status_t H2BGraphicBufferProducer::dequeueBuffer(
141 int* slot, sp<BFence>* fence,
142 uint32_t w, uint32_t h,
143 PixelFormat format, uint64_t usage,
144 uint64_t* outBufferAge, FrameEventHistoryDelta* /* outTimestamps */) {
145
146 using HInput = HGraphicBufferProducer::DequeueBufferInput;
147 HInput input{w, h, static_cast<uint32_t>(format), usage};
148
149 using HOutput = HGraphicBufferProducer::DequeueBufferOutput;
150 bool converted{};
151 status_t bStatus{};
152 Return<void> transResult = mBase->dequeueBuffer(input,
153 [&converted, &bStatus, slot, fence, outBufferAge] (
154 HStatus hStatus, int32_t hSlot, HOutput const& hOutput) {
155 converted = h2b(hStatus, &bStatus);
156 if (!converted || bStatus != OK) {
157 return;
158 }
159 *slot = hSlot;
160 *outBufferAge = hOutput.bufferAge;
161 bStatus =
162 (hOutput.bufferNeedsReallocation ?
163 BUFFER_NEEDS_REALLOCATION : 0) |
164 (hOutput.releaseAllBuffers ?
165 RELEASE_ALL_BUFFERS : 0);
166 converted = h2b(hOutput.fence, fence);
167 });
168 if (!transResult.isOk()) {
169 LOG(ERROR) << "dequeueBuffer: transaction failed.";
170 return FAILED_TRANSACTION;
171 }
172 if (!converted) {
173 LOG(ERROR) << "dequeueBuffer: corrupted transaction.";
174 return FAILED_TRANSACTION;
175 }
176 return bStatus;
177 }
178
detachBuffer(int slot)179 status_t H2BGraphicBufferProducer::detachBuffer(int slot) {
180 status_t bStatus{};
181 Return<HStatus> transResult = mBase->detachBuffer(
182 static_cast<int32_t>(slot));
183 if (!transResult.isOk()) {
184 LOG(ERROR) << "detachBuffer: transaction failed.";
185 return FAILED_TRANSACTION;
186 }
187 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
188 LOG(ERROR) << "detachBuffer: corrupted transaction.";
189 return FAILED_TRANSACTION;
190 }
191 return bStatus;
192 }
193
detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<BFence> * outFence)194 status_t H2BGraphicBufferProducer::detachNextBuffer(
195 sp<GraphicBuffer>* outBuffer, sp<BFence>* outFence) {
196 bool converted{};
197 status_t bStatus{};
198 Return<void> transResult = mBase->detachNextBuffer(
199 [&converted, &bStatus, outBuffer, outFence] (
200 HStatus hStatus,
201 HardwareBuffer const& hBuffer,
202 hidl_handle const& hFence) {
203 converted = h2b(hStatus, &bStatus) &&
204 h2b(hBuffer, outBuffer) &&
205 h2b(hFence, outFence);
206 });
207 if (!transResult.isOk()) {
208 LOG(ERROR) << "detachNextBuffer: transaction failed.";
209 return FAILED_TRANSACTION;
210 }
211 if (!converted) {
212 LOG(ERROR) << "detachNextBuffer: corrupted transaction.";
213 return FAILED_TRANSACTION;
214 }
215 return bStatus;
216 }
217
attachBuffer(int * outSlot,sp<GraphicBuffer> const & buffer)218 status_t H2BGraphicBufferProducer::attachBuffer(
219 int* outSlot, sp<GraphicBuffer> const& buffer) {
220 HardwareBuffer hBuffer{};
221 uint32_t hGenerationNumber{};
222 if (!b2h(buffer, &hBuffer, &hGenerationNumber)) {
223 LOG(ERROR) << "attachBuffer: invalid input buffer.";
224 return BAD_VALUE;
225 }
226
227 bool converted{};
228 status_t bStatus{};
229 Return<void> transResult = mBase->attachBuffer(hBuffer, hGenerationNumber,
230 [&converted, &bStatus, outSlot](
231 HStatus hStatus, int32_t hSlot, bool releaseAllBuffers) {
232 converted = h2b(hStatus, &bStatus);
233 *outSlot = static_cast<int>(hSlot);
234 if (converted && releaseAllBuffers && bStatus == OK) {
235 bStatus = IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
236 }
237 });
238 if (!transResult.isOk()) {
239 LOG(ERROR) << "attachBuffer: transaction failed.";
240 return FAILED_TRANSACTION;
241 }
242 if (!converted) {
243 LOG(ERROR) << "attachBuffer: corrupted transaction.";
244 return FAILED_TRANSACTION;
245 }
246 return bStatus;
247 }
248
queueBuffer(int slot,QueueBufferInput const & input,QueueBufferOutput * output)249 status_t H2BGraphicBufferProducer::queueBuffer(
250 int slot,
251 QueueBufferInput const& input,
252 QueueBufferOutput* output) {
253 HQueueBufferInput hInput{};
254 HFenceWrapper hFenceWrapper;
255 if (!b2h(input, &hInput, &hFenceWrapper)) {
256 LOG(ERROR) << "queueBuffer: corrupted input.";
257 return UNKNOWN_ERROR;
258 }
259
260 bool converted{};
261 status_t bStatus{};
262 Return<void> transResult = mBase->queueBuffer(
263 static_cast<int32_t>(slot),
264 hInput,
265 [&converted, &bStatus, output](
266 HStatus hStatus,
267 HQueueBufferOutput const& hOutput) {
268 converted = h2b(hStatus, &bStatus) && h2b(hOutput, output);
269 });
270
271 if (!transResult.isOk()) {
272 LOG(ERROR) << "queueBuffer: transaction failed.";
273 return FAILED_TRANSACTION;
274 }
275 if (!converted) {
276 LOG(ERROR) << "queueBuffer: corrupted transaction.";
277 return FAILED_TRANSACTION;
278 }
279 return bStatus;
280 }
281
cancelBuffer(int slot,sp<BFence> const & fence)282 status_t H2BGraphicBufferProducer::cancelBuffer(int slot, sp<BFence> const& fence) {
283 HFenceWrapper hFenceWrapper;
284 if (!b2h(fence, &hFenceWrapper)) {
285 LOG(ERROR) << "cancelBuffer: corrupted input fence.";
286 return UNKNOWN_ERROR;
287 }
288 status_t bStatus{};
289 Return<HStatus> transResult = mBase->cancelBuffer(
290 static_cast<int32_t>(slot),
291 hFenceWrapper.getHandle());
292 if (!transResult.isOk()) {
293 LOG(ERROR) << "cancelBuffer: transaction failed.";
294 return FAILED_TRANSACTION;
295 }
296 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
297 LOG(ERROR) << "cancelBuffer: corrupted transaction.";
298 return FAILED_TRANSACTION;
299 }
300 return bStatus;
301 }
302
query(int what,int * value)303 int H2BGraphicBufferProducer::query(int what, int* value) {
304 int result{};
305 Return<void> transResult = mBase->query(
306 static_cast<int32_t>(what),
307 [&result, value](int32_t r, int32_t v) {
308 result = static_cast<int>(r);
309 *value = static_cast<int>(v);
310 });
311 if (!transResult.isOk()) {
312 LOG(ERROR) << "query: transaction failed.";
313 return FAILED_TRANSACTION;
314 }
315 return result;
316 }
317
connect(sp<IProducerListener> const & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)318 status_t H2BGraphicBufferProducer::connect(
319 sp<IProducerListener> const& listener, int api,
320 bool producerControlledByApp, QueueBufferOutput* output) {
321 HConnectionType hConnectionType;
322 if (!b2h(api, &hConnectionType)) {
323 LOG(ERROR) << "connect: corrupted input connection type.";
324 return UNKNOWN_ERROR;
325 }
326 sp<HProducerListener> hListener = nullptr;
327 if (listener && listener->needsReleaseNotify()) {
328 hListener = new B2HProducerListener(listener);
329 if (!hListener) {
330 LOG(ERROR) << "connect: failed to wrap listener.";
331 return UNKNOWN_ERROR;
332 }
333 }
334
335 bool converted{};
336 status_t bStatus{};
337 Return<void> transResult = mBase->connect(
338 hListener,
339 hConnectionType,
340 producerControlledByApp,
341 [&converted, &bStatus, output](
342 HStatus hStatus,
343 HQueueBufferOutput const& hOutput) {
344 converted = h2b(hStatus, &bStatus) && h2b(hOutput, output);
345 });
346 if (!transResult.isOk()) {
347 LOG(ERROR) << "connect: transaction failed.";
348 return FAILED_TRANSACTION;
349 }
350 if (!converted) {
351 LOG(ERROR) << "connect: corrupted transaction.";
352 return FAILED_TRANSACTION;
353 }
354 return bStatus;
355
356 }
357
disconnect(int api,DisconnectMode mode)358 status_t H2BGraphicBufferProducer::disconnect(int api, DisconnectMode mode) {
359 HConnectionType hConnectionType;
360 if (mode == DisconnectMode::AllLocal) {
361 hConnectionType = HConnectionType::CURRENTLY_CONNECTED;
362 } else if (!b2h(api, &hConnectionType)) {
363 LOG(ERROR) << "connect: corrupted input connection type.";
364 return UNKNOWN_ERROR;
365 }
366
367 status_t bStatus{};
368 Return<HStatus> transResult = mBase->disconnect(hConnectionType);
369 if (!transResult.isOk()) {
370 LOG(ERROR) << "disconnect: transaction failed.";
371 return FAILED_TRANSACTION;
372 }
373 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
374 LOG(ERROR) << "disconnect: corrupted transaction.";
375 return FAILED_TRANSACTION;
376 }
377 return bStatus;
378 }
379
setSidebandStream(sp<NativeHandle> const & stream)380 status_t H2BGraphicBufferProducer::setSidebandStream(
381 sp<NativeHandle> const& stream) {
382 if (stream) {
383 LOG(INFO) << "setSidebandStream: not supported.";
384 return INVALID_OPERATION;
385 }
386 return OK;
387 }
388
allocateBuffers(uint32_t width,uint32_t height,PixelFormat format,uint64_t usage)389 void H2BGraphicBufferProducer::allocateBuffers(
390 uint32_t width, uint32_t height,
391 PixelFormat format, uint64_t usage) {
392 status_t bStatus{};
393 Return<HStatus> transResult = mBase->allocateBuffers(
394 width, height, static_cast<uint32_t>(format), usage);
395 if (!transResult.isOk()) {
396 LOG(ERROR) << "allocateBuffer: transaction failed.";
397 return;
398 }
399 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
400 LOG(ERROR) << "allocateBuffer: corrupted transaction.";
401 return;
402 }
403 }
404
allowAllocation(bool allow)405 status_t H2BGraphicBufferProducer::allowAllocation(bool allow) {
406 status_t bStatus{};
407 Return<HStatus> transResult = mBase->allowAllocation(allow);
408 if (!transResult.isOk()) {
409 LOG(ERROR) << "allowAllocation: transaction failed.";
410 return FAILED_TRANSACTION;
411 }
412 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
413 LOG(ERROR) << "allowAllocation: corrupted transaction.";
414 return FAILED_TRANSACTION;
415 }
416 return bStatus;
417 }
418
setGenerationNumber(uint32_t generationNumber)419 status_t H2BGraphicBufferProducer::setGenerationNumber(
420 uint32_t generationNumber) {
421 status_t bStatus{};
422 Return<HStatus> transResult = mBase->setGenerationNumber(generationNumber);
423 if (!transResult.isOk()) {
424 LOG(ERROR) << "setGenerationNumber: transaction failed.";
425 return FAILED_TRANSACTION;
426 }
427 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
428 LOG(ERROR) << "setGenerationNumber: corrupted transaction.";
429 return FAILED_TRANSACTION;
430 }
431 return bStatus;
432 }
433
getConsumerName() const434 String8 H2BGraphicBufferProducer::getConsumerName() const {
435 String8 bName;
436 Return<void> transResult = mBase->getConsumerName(
437 [&bName](hidl_string const& name) {
438 bName = name.c_str();
439 });
440 return bName;
441 }
442
setSharedBufferMode(bool sharedBufferMode)443 status_t H2BGraphicBufferProducer::setSharedBufferMode(bool sharedBufferMode) {
444 if (sharedBufferMode) {
445 LOG(INFO) << "setSharedBufferMode: not supported.";
446 return INVALID_OPERATION;
447 }
448 return OK;
449 }
450
setAutoRefresh(bool autoRefresh)451 status_t H2BGraphicBufferProducer::setAutoRefresh(bool autoRefresh) {
452 if (autoRefresh) {
453 LOG(INFO) << "setAutoRefresh: not supported.";
454 return INVALID_OPERATION;
455 }
456 return OK;
457 }
458
setDequeueTimeout(nsecs_t timeout)459 status_t H2BGraphicBufferProducer::setDequeueTimeout(nsecs_t timeout) {
460 status_t bStatus{};
461 Return<HStatus> transResult = mBase->setDequeueTimeout(
462 static_cast<int64_t>(timeout));
463 if (!transResult.isOk()) {
464 LOG(ERROR) << "setDequeueTimeout: transaction failed.";
465 return FAILED_TRANSACTION;
466 }
467 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) {
468 LOG(ERROR) << "setDequeueTimeout: corrupted transaction.";
469 return FAILED_TRANSACTION;
470 }
471 return bStatus;
472 }
473
getLastQueuedBuffer(sp<GraphicBuffer> *,sp<BFence> *,float[16])474 status_t H2BGraphicBufferProducer::getLastQueuedBuffer(
475 sp<GraphicBuffer>*,
476 sp<BFence>*,
477 float[16]) {
478 LOG(INFO) << "getLastQueuedBuffer: not supported.";
479 return INVALID_OPERATION;
480 }
481
getFrameTimestamps(FrameEventHistoryDelta *)482 void H2BGraphicBufferProducer::getFrameTimestamps(FrameEventHistoryDelta*) {
483 LOG(INFO) << "getFrameTimestamps: not supported.";
484 }
485
getUniqueId(uint64_t * outId) const486 status_t H2BGraphicBufferProducer::getUniqueId(uint64_t* outId) const {
487 Return<uint64_t> transResult = mBase->getUniqueId();
488 if (!transResult.isOk()) {
489 LOG(ERROR) << "getUniqueId: transaction failed.";
490 return FAILED_TRANSACTION;
491 }
492 *outId = static_cast<uint64_t>(transResult);
493 return OK;
494 }
495
getConsumerUsage(uint64_t *) const496 status_t H2BGraphicBufferProducer::getConsumerUsage(uint64_t*) const {
497 LOG(INFO) << "getConsumerUsage: not supported.";
498 return INVALID_OPERATION;
499 }
500
501 } // namespace utils
502 } // namespace V2_0
503 } // namespace bufferqueue
504 } // namespace graphics
505 } // namespace hardware
506 } // namespace android
507