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 "B2HGraphicBufferProducer@2.0"
19 
20 #include <android-base/logging.h>
21 
22 #include <android/hardware/graphics/bufferqueue/2.0/types.h>
23 #include <android/hardware/graphics/common/1.2/types.h>
24 #include <gui/bufferqueue/2.0/H2BProducerListener.h>
25 #include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
26 #include <gui/bufferqueue/2.0/types.h>
27 #include <ui/GraphicBuffer.h>
28 #include <ui/Rect.h>
29 #include <ui/Region.h>
30 #include <vndk/hardware_buffer.h>
31 
32 namespace android {
33 namespace hardware {
34 namespace graphics {
35 namespace bufferqueue {
36 namespace V2_0 {
37 namespace utils {
38 
39 namespace /* unnamed */ {
40 
41 using BQueueBufferInput = ::android::
42         IGraphicBufferProducer::QueueBufferInput;
43 using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0::
44         IGraphicBufferProducer::QueueBufferInput;
45 using BQueueBufferOutput = ::android::
46         IGraphicBufferProducer::QueueBufferOutput;
47 using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0::
48         IGraphicBufferProducer::QueueBufferOutput;
49 
50 using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
51 using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
52 
b2h(BQueueBufferOutput const & from,HQueueBufferOutput * to)53 bool b2h(BQueueBufferOutput const& from, HQueueBufferOutput* to) {
54     to->width = from.width;
55     to->height = from.height;
56     to->transformHint = static_cast<int32_t>(from.transformHint);
57     to->numPendingBuffers = from.numPendingBuffers;
58     to->nextFrameNumber = from.nextFrameNumber;
59     to->bufferReplaced = from.bufferReplaced;
60     return true;
61 }
62 
63 } // unnamed namespace
64 
65 // B2HGraphicBufferProducer
66 // ========================
67 
B2HGraphicBufferProducer(sp<BGraphicBufferProducer> const & base)68 B2HGraphicBufferProducer::B2HGraphicBufferProducer(
69         sp<BGraphicBufferProducer> const& base)
70       : mBase{base} {
71 }
72 
setMaxDequeuedBufferCount(int32_t maxDequeuedBuffers)73 Return<HStatus> B2HGraphicBufferProducer::setMaxDequeuedBufferCount(
74         int32_t maxDequeuedBuffers) {
75     HStatus hStatus{};
76     bool converted = b2h(
77             mBase->setMaxDequeuedBufferCount(
78                 static_cast<int>(maxDequeuedBuffers)),
79             &hStatus);
80     return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
81 }
82 
requestBuffer(int32_t slot,requestBuffer_cb _hidl_cb)83 Return<void> B2HGraphicBufferProducer::requestBuffer(
84         int32_t slot,
85         requestBuffer_cb _hidl_cb) {
86     sp<GraphicBuffer> bBuffer;
87     HStatus hStatus{};
88     HardwareBuffer hBuffer{};
89     uint32_t hGenerationNumber{};
90     bool converted =
91             b2h(mBase->requestBuffer(
92                     static_cast<int>(slot), &bBuffer),
93                 &hStatus) &&
94             b2h(bBuffer, &hBuffer, &hGenerationNumber);
95     _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
96              hBuffer, hGenerationNumber);
97     return {};
98 }
99 
setAsyncMode(bool async)100 Return<HStatus> B2HGraphicBufferProducer::setAsyncMode(bool async) {
101     HStatus hStatus{};
102     bool converted = b2h(mBase->setAsyncMode(async), &hStatus);
103     return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
104 }
105 
dequeueBuffer(DequeueBufferInput const & input,dequeueBuffer_cb _hidl_cb)106 Return<void> B2HGraphicBufferProducer::dequeueBuffer(
107         DequeueBufferInput const& input,
108         dequeueBuffer_cb _hidl_cb) {
109     int bSlot{};
110     sp<BFence> bFence;
111     HStatus hStatus{};
112     DequeueBufferOutput hOutput{};
113     HFenceWrapper hFenceWrapper;
114     bool converted =
115             b2h(mBase->dequeueBuffer(
116                     &bSlot,
117                     &bFence,
118                     input.width,
119                     input.height,
120                     static_cast<PixelFormat>(input.format),
121                     input.usage,
122                     &hOutput.bufferAge,
123                     nullptr /* outTimestamps */),
124                 &hStatus,
125                 &hOutput.bufferNeedsReallocation,
126                 &hOutput.releaseAllBuffers) &&
127             b2h(bFence, &hFenceWrapper);
128     hOutput.fence = hFenceWrapper.getHandle();
129     _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
130              static_cast<int32_t>(bSlot),
131              hOutput);
132     return {};
133 }
134 
detachBuffer(int32_t slot)135 Return<HStatus> B2HGraphicBufferProducer::detachBuffer(int32_t slot) {
136     HStatus hStatus{};
137     bool converted = b2h(
138             mBase->detachBuffer(static_cast<int>(slot)), &hStatus);
139     return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
140 }
141 
detachNextBuffer(detachNextBuffer_cb _hidl_cb)142 Return<void> B2HGraphicBufferProducer::detachNextBuffer(
143         detachNextBuffer_cb _hidl_cb) {
144     sp<GraphicBuffer> bBuffer;
145     sp<BFence> bFence;
146     HStatus hStatus{};
147     HardwareBuffer hBuffer{};
148     HFenceWrapper hFenceWrapper;
149     bool converted =
150             b2h(mBase->detachNextBuffer(&bBuffer, &bFence), &hStatus) &&
151             b2h(bBuffer, &hBuffer) &&
152             b2h(bFence, &hFenceWrapper);
153     _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
154              hBuffer,
155              hFenceWrapper.getHandle());
156     return {};
157 }
158 
attachBuffer(HardwareBuffer const & hBuffer,uint32_t generationNumber,attachBuffer_cb _hidl_cb)159 Return<void> B2HGraphicBufferProducer::attachBuffer(
160         HardwareBuffer const& hBuffer,
161         uint32_t generationNumber,
162         attachBuffer_cb _hidl_cb) {
163     sp<GraphicBuffer> bBuffer;
164     if (!h2b(hBuffer, &bBuffer) || !bBuffer) {
165         _hidl_cb(HStatus::UNKNOWN_ERROR,
166                  static_cast<int32_t>(SlotIndex::INVALID),
167                  false);
168         return {};
169     }
170     bBuffer->setGenerationNumber(generationNumber);
171 
172     int bSlot{};
173     HStatus hStatus{};
174     bool releaseAllBuffers{};
175     bool converted = b2h(
176             mBase->attachBuffer(&bSlot, bBuffer), &hStatus,
177             nullptr /* bufferNeedsReallocation */,
178             &releaseAllBuffers);
179     _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
180              static_cast<int32_t>(bSlot),
181              releaseAllBuffers);
182     return {};
183 }
184 
queueBuffer(int32_t slot,QueueBufferInput const & hInput,queueBuffer_cb _hidl_cb)185 Return<void> B2HGraphicBufferProducer::queueBuffer(
186         int32_t slot,
187         QueueBufferInput const& hInput,
188         queueBuffer_cb _hidl_cb) {
189     BQueueBufferInput bInput{
190             hInput.timestamp,
191             hInput.isAutoTimestamp,
192             static_cast<android_dataspace>(hInput.dataSpace),
193             {}, /* crop */
194             0 /* scalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE */,
195             static_cast<uint32_t>(hInput.transform),
196             {}, /* fence */
197             static_cast<uint32_t>(hInput.stickyTransform),
198             false /* getFrameTimestamps */};
199 
200     // Convert crop.
201     if (!h2b(hInput.crop, &bInput.crop)) {
202         _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
203         return {};
204     }
205 
206     // Convert surfaceDamage.
207     if (!h2b(hInput.surfaceDamage, &bInput.surfaceDamage)) {
208         _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
209         return {};
210     }
211 
212     // Convert fence.
213     if (!h2b(hInput.fence, &bInput.fence)) {
214         _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
215         return {};
216     }
217 
218     BQueueBufferOutput bOutput{};
219     HStatus hStatus{};
220     QueueBufferOutput hOutput{};
221     bool converted =
222             b2h(
223                 mBase->queueBuffer(static_cast<int>(slot), bInput, &bOutput),
224                 &hStatus) &&
225             b2h(bOutput, &hOutput);
226 
227     _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput);
228     return {};
229 }
230 
cancelBuffer(int32_t slot,hidl_handle const & fence)231 Return<HStatus> B2HGraphicBufferProducer::cancelBuffer(
232         int32_t slot,
233         hidl_handle const& fence) {
234     sp<BFence> bFence;
235     if (!h2b(fence.getNativeHandle(), &bFence)) {
236         return {HStatus::UNKNOWN_ERROR};
237     }
238     HStatus hStatus{};
239     bool converted = b2h(
240             mBase->cancelBuffer(static_cast<int>(slot), bFence),
241             &hStatus);
242     return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
243 }
244 
query(int32_t what,query_cb _hidl_cb)245 Return<void> B2HGraphicBufferProducer::query(int32_t what, query_cb _hidl_cb) {
246     int value{};
247     int result = mBase->query(static_cast<int>(what), &value);
248     _hidl_cb(static_cast<int32_t>(result), static_cast<int32_t>(value));
249     return {};
250 }
251 
252 struct Obituary : public hardware::hidl_death_recipient {
253     wp<B2HGraphicBufferProducer> producer;
254     sp<HProducerListener> listener;
255     HConnectionType apiType;
Obituaryandroid::hardware::graphics::bufferqueue::V2_0::utils::Obituary256     Obituary(const wp<B2HGraphicBufferProducer>& p,
257              const sp<HProducerListener>& l,
258              HConnectionType t)
259         : producer(p), listener(l), apiType(t) {}
260 
serviceDiedandroid::hardware::graphics::bufferqueue::V2_0::utils::Obituary261     void serviceDied(uint64_t /* cookie */,
262             const wp<::android::hidl::base::V1_0::IBase>& /* who */) override {
263         sp<B2HGraphicBufferProducer> dr = producer.promote();
264         if (dr != nullptr) {
265             (void)dr->disconnect(apiType);
266         }
267     }
268 };
269 
connect(sp<HProducerListener> const & hListener,HConnectionType hConnectionType,bool producerControlledByApp,connect_cb _hidl_cb)270 Return<void> B2HGraphicBufferProducer::connect(
271         sp<HProducerListener> const& hListener,
272         HConnectionType hConnectionType,
273         bool producerControlledByApp,
274         connect_cb _hidl_cb) {
275     sp<BProducerListener> bListener = new H2BProducerListener(hListener);
276     int bConnectionType{};
277     if (!bListener || !h2b(hConnectionType, &bConnectionType)) {
278         _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
279         return {};
280     }
281     BQueueBufferOutput bOutput{};
282     HStatus hStatus{};
283     QueueBufferOutput hOutput{};
284     bool converted =
285             b2h(mBase->connect(bListener,
286                                bConnectionType,
287                                producerControlledByApp,
288                                &bOutput),
289                 &hStatus) &&
290             b2h(bOutput, &hOutput);
291 #ifdef NO_BINDER
292     if (converted && hListener != nullptr) {
293         mObituary = new Obituary(this, hListener, hConnectionType);
294         hListener->linkToDeath(mObituary, 0);
295     }
296 #endif // NO_BINDER
297     _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput);
298     return {};
299 }
300 
disconnect(HConnectionType hConnectionType)301 Return<HStatus> B2HGraphicBufferProducer::disconnect(
302         HConnectionType hConnectionType) {
303     int bConnectionType;
304     if (!h2b(hConnectionType, &bConnectionType)) {
305         return {HStatus::UNKNOWN_ERROR};
306     }
307     HStatus hStatus{};
308     bool converted = b2h(mBase->disconnect(bConnectionType), &hStatus);
309 #ifdef NO_BINDER
310     if (mObituary != nullptr) {
311         mObituary->listener->unlinkToDeath(mObituary);
312         mObituary.clear();
313     }
314 #endif // NO_BINDER
315     return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
316 }
317 
allocateBuffers(uint32_t width,uint32_t height,uint32_t format,uint64_t usage)318 Return<HStatus> B2HGraphicBufferProducer::allocateBuffers(
319         uint32_t width, uint32_t height,
320         uint32_t format, uint64_t usage) {
321     mBase->allocateBuffers(
322             width, height, static_cast<PixelFormat>(format), usage);
323     return {HStatus::OK};
324 }
325 
allowAllocation(bool allow)326 Return<HStatus> B2HGraphicBufferProducer::allowAllocation(bool allow) {
327     HStatus hStatus{};
328     bool converted = b2h(mBase->allowAllocation(allow), &hStatus);
329     return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
330 }
331 
setGenerationNumber(uint32_t generationNumber)332 Return<HStatus> B2HGraphicBufferProducer::setGenerationNumber(
333         uint32_t generationNumber) {
334     HStatus hStatus{};
335     bool converted = b2h(
336             mBase->setGenerationNumber(generationNumber),
337             &hStatus);
338     return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
339 }
340 
setDequeueTimeout(int64_t timeoutNs)341 Return<HStatus> B2HGraphicBufferProducer::setDequeueTimeout(
342         int64_t timeoutNs) {
343     HStatus hStatus{};
344     bool converted = b2h(
345             mBase->setDequeueTimeout(static_cast<nsecs_t>(timeoutNs)),
346             &hStatus);
347     return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
348 }
349 
getUniqueId()350 Return<uint64_t> B2HGraphicBufferProducer::getUniqueId() {
351     uint64_t outId{};
352     HStatus hStatus{};
353     bool converted = b2h(mBase->getUniqueId(&outId), &hStatus);
354     return {converted ? outId : 0};
355 }
356 
getConsumerName(getConsumerName_cb _hidl_cb)357 Return<void> B2HGraphicBufferProducer::getConsumerName(
358         getConsumerName_cb _hidl_cb) {
359     _hidl_cb(hidl_string{mBase->getConsumerName().c_str()});
360     return {};
361 }
362 
363 }  // namespace utils
364 }  // namespace V2_0
365 }  // namespace bufferqueue
366 }  // namespace graphics
367 }  // namespace hardware
368 }  // namespace android
369 
370