IGraphicBufferProducer.cpp revision 7dde599bf1a0dbef7390d91c2689d506371cdbd7
1/*
2 * Copyright (C) 2010 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#include <stdint.h>
18#include <sys/types.h>
19
20#include <utils/Errors.h>
21#include <utils/NativeHandle.h>
22#include <utils/RefBase.h>
23#include <utils/Timers.h>
24#include <utils/Vector.h>
25
26#include <binder/Parcel.h>
27#include <binder/IInterface.h>
28
29#include <gui/IGraphicBufferProducer.h>
30#include <gui/IProducerListener.h>
31
32namespace android {
33// ----------------------------------------------------------------------------
34
35enum {
36    REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
37    DEQUEUE_BUFFER,
38    DETACH_BUFFER,
39    DETACH_NEXT_BUFFER,
40    ATTACH_BUFFER,
41    QUEUE_BUFFER,
42    CANCEL_BUFFER,
43    QUERY,
44    CONNECT,
45    DISCONNECT,
46    SET_SIDEBAND_STREAM,
47    ALLOCATE_BUFFERS,
48    ALLOW_ALLOCATION,
49    SET_GENERATION_NUMBER,
50    GET_CONSUMER_NAME,
51    SET_MAX_DEQUEUED_BUFFER_COUNT,
52    SET_ASYNC_MODE,
53    GET_NEXT_FRAME_NUMBER
54};
55
56class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
57{
58public:
59    BpGraphicBufferProducer(const sp<IBinder>& impl)
60        : BpInterface<IGraphicBufferProducer>(impl)
61    {
62    }
63
64    virtual ~BpGraphicBufferProducer();
65
66    virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
67        Parcel data, reply;
68        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
69        data.writeInt32(bufferIdx);
70        status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
71        if (result != NO_ERROR) {
72            return result;
73        }
74        bool nonNull = reply.readInt32();
75        if (nonNull) {
76            *buf = new GraphicBuffer();
77            result = reply.read(**buf);
78            if(result != NO_ERROR) {
79                (*buf).clear();
80                return result;
81            }
82        }
83        result = reply.readInt32();
84        return result;
85    }
86
87    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
88        Parcel data, reply;
89        data.writeInterfaceToken(
90                IGraphicBufferProducer::getInterfaceDescriptor());
91        data.writeInt32(maxDequeuedBuffers);
92        status_t result = remote()->transact(SET_MAX_DEQUEUED_BUFFER_COUNT,
93                data, &reply);
94        if (result != NO_ERROR) {
95            return result;
96        }
97        result = reply.readInt32();
98        return result;
99    }
100
101    virtual status_t setAsyncMode(bool async) {
102        Parcel data, reply;
103        data.writeInterfaceToken(
104                IGraphicBufferProducer::getInterfaceDescriptor());
105        data.writeInt32(async);
106        status_t result = remote()->transact(SET_ASYNC_MODE,
107                data, &reply);
108        if (result != NO_ERROR) {
109            return result;
110        }
111        result = reply.readInt32();
112        return result;
113    }
114
115    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
116            uint32_t height, PixelFormat format, uint32_t usage) {
117        Parcel data, reply;
118        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
119        data.writeUint32(width);
120        data.writeUint32(height);
121        data.writeInt32(static_cast<int32_t>(format));
122        data.writeUint32(usage);
123        status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
124        if (result != NO_ERROR) {
125            return result;
126        }
127        *buf = reply.readInt32();
128        bool nonNull = reply.readInt32();
129        if (nonNull) {
130            *fence = new Fence();
131            reply.read(**fence);
132        }
133        result = reply.readInt32();
134        return result;
135    }
136
137    virtual status_t detachBuffer(int slot) {
138        Parcel data, reply;
139        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
140        data.writeInt32(slot);
141        status_t result = remote()->transact(DETACH_BUFFER, data, &reply);
142        if (result != NO_ERROR) {
143            return result;
144        }
145        result = reply.readInt32();
146        return result;
147    }
148
149    virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
150            sp<Fence>* outFence) {
151        if (outBuffer == NULL) {
152            ALOGE("detachNextBuffer: outBuffer must not be NULL");
153            return BAD_VALUE;
154        } else if (outFence == NULL) {
155            ALOGE("detachNextBuffer: outFence must not be NULL");
156            return BAD_VALUE;
157        }
158        Parcel data, reply;
159        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
160        status_t result = remote()->transact(DETACH_NEXT_BUFFER, data, &reply);
161        if (result != NO_ERROR) {
162            return result;
163        }
164        result = reply.readInt32();
165        if (result == NO_ERROR) {
166            bool nonNull = reply.readInt32();
167            if (nonNull) {
168                *outBuffer = new GraphicBuffer;
169                reply.read(**outBuffer);
170            }
171            nonNull = reply.readInt32();
172            if (nonNull) {
173                *outFence = new Fence;
174                reply.read(**outFence);
175            }
176        }
177        return result;
178    }
179
180    virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
181        Parcel data, reply;
182        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
183        data.write(*buffer.get());
184        status_t result = remote()->transact(ATTACH_BUFFER, data, &reply);
185        if (result != NO_ERROR) {
186            return result;
187        }
188        *slot = reply.readInt32();
189        result = reply.readInt32();
190        return result;
191    }
192
193    virtual status_t queueBuffer(int buf,
194            const QueueBufferInput& input, QueueBufferOutput* output) {
195        Parcel data, reply;
196        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
197        data.writeInt32(buf);
198        data.write(input);
199        status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
200        if (result != NO_ERROR) {
201            return result;
202        }
203        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
204        result = reply.readInt32();
205        return result;
206    }
207
208    virtual status_t cancelBuffer(int buf, const sp<Fence>& fence) {
209        Parcel data, reply;
210        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
211        data.writeInt32(buf);
212        data.write(*fence.get());
213        status_t result = remote()->transact(CANCEL_BUFFER, data, &reply);
214        if (result != NO_ERROR) {
215            return result;
216        }
217        result = reply.readInt32();
218        return result;
219    }
220
221    virtual int query(int what, int* value) {
222        Parcel data, reply;
223        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
224        data.writeInt32(what);
225        status_t result = remote()->transact(QUERY, data, &reply);
226        if (result != NO_ERROR) {
227            return result;
228        }
229        value[0] = reply.readInt32();
230        result = reply.readInt32();
231        return result;
232    }
233
234    virtual status_t connect(const sp<IProducerListener>& listener,
235            int api, bool producerControlledByApp, QueueBufferOutput* output) {
236        Parcel data, reply;
237        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
238        if (listener != NULL) {
239            data.writeInt32(1);
240            data.writeStrongBinder(IInterface::asBinder(listener));
241        } else {
242            data.writeInt32(0);
243        }
244        data.writeInt32(api);
245        data.writeInt32(producerControlledByApp);
246        status_t result = remote()->transact(CONNECT, data, &reply);
247        if (result != NO_ERROR) {
248            return result;
249        }
250        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
251        result = reply.readInt32();
252        return result;
253    }
254
255    virtual status_t disconnect(int api) {
256        Parcel data, reply;
257        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
258        data.writeInt32(api);
259        status_t result =remote()->transact(DISCONNECT, data, &reply);
260        if (result != NO_ERROR) {
261            return result;
262        }
263        result = reply.readInt32();
264        return result;
265    }
266
267    virtual status_t setSidebandStream(const sp<NativeHandle>& stream) {
268        Parcel data, reply;
269        status_t result;
270        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
271        if (stream.get()) {
272            data.writeInt32(true);
273            data.writeNativeHandle(stream->handle());
274        } else {
275            data.writeInt32(false);
276        }
277        if ((result = remote()->transact(SET_SIDEBAND_STREAM, data, &reply)) == NO_ERROR) {
278            result = reply.readInt32();
279        }
280        return result;
281    }
282
283    virtual void allocateBuffers(uint32_t width, uint32_t height,
284            PixelFormat format, uint32_t usage) {
285        Parcel data, reply;
286        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
287        data.writeUint32(width);
288        data.writeUint32(height);
289        data.writeInt32(static_cast<int32_t>(format));
290        data.writeUint32(usage);
291        status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
292        if (result != NO_ERROR) {
293            ALOGE("allocateBuffers failed to transact: %d", result);
294        }
295    }
296
297    virtual status_t allowAllocation(bool allow) {
298        Parcel data, reply;
299        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
300        data.writeInt32(static_cast<int32_t>(allow));
301        status_t result = remote()->transact(ALLOW_ALLOCATION, data, &reply);
302        if (result != NO_ERROR) {
303            return result;
304        }
305        result = reply.readInt32();
306        return result;
307    }
308
309    virtual status_t setGenerationNumber(uint32_t generationNumber) {
310        Parcel data, reply;
311        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
312        data.writeUint32(generationNumber);
313        status_t result = remote()->transact(SET_GENERATION_NUMBER, data, &reply);
314        if (result == NO_ERROR) {
315            result = reply.readInt32();
316        }
317        return result;
318    }
319
320    virtual String8 getConsumerName() const {
321        Parcel data, reply;
322        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
323        status_t result = remote()->transact(GET_CONSUMER_NAME, data, &reply);
324        if (result != NO_ERROR) {
325            ALOGE("getConsumerName failed to transact: %d", result);
326            return String8("TransactFailed");
327        }
328        return reply.readString8();
329    }
330
331    virtual uint64_t getNextFrameNumber() const {
332        Parcel data, reply;
333        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
334        status_t result = remote()->transact(GET_NEXT_FRAME_NUMBER, data, &reply);
335        if (result != NO_ERROR) {
336            ALOGE("getNextFrameNumber failed to transact: %d", result);
337            return 0;
338        }
339        uint64_t frameNumber = reply.readUint64();
340        return frameNumber;
341    }
342};
343
344// Out-of-line virtual method definition to trigger vtable emission in this
345// translation unit (see clang warning -Wweak-vtables)
346BpGraphicBufferProducer::~BpGraphicBufferProducer() {}
347
348IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
349
350// ----------------------------------------------------------------------
351
352status_t BnGraphicBufferProducer::onTransact(
353    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
354{
355    switch(code) {
356        case REQUEST_BUFFER: {
357            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
358            int bufferIdx   = data.readInt32();
359            sp<GraphicBuffer> buffer;
360            int result = requestBuffer(bufferIdx, &buffer);
361            reply->writeInt32(buffer != 0);
362            if (buffer != 0) {
363                reply->write(*buffer);
364            }
365            reply->writeInt32(result);
366            return NO_ERROR;
367        }
368        case SET_MAX_DEQUEUED_BUFFER_COUNT: {
369            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
370            int maxDequeuedBuffers = data.readInt32();
371            int result = setMaxDequeuedBufferCount(maxDequeuedBuffers);
372            reply->writeInt32(result);
373            return NO_ERROR;
374        }
375        case SET_ASYNC_MODE: {
376            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
377            bool async = data.readInt32();
378            int result = setAsyncMode(async);
379            reply->writeInt32(result);
380            return NO_ERROR;
381        }
382        case DEQUEUE_BUFFER: {
383            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
384            uint32_t width = data.readUint32();
385            uint32_t height = data.readUint32();
386            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
387            uint32_t usage = data.readUint32();
388            int buf = 0;
389            sp<Fence> fence;
390            int result = dequeueBuffer(&buf, &fence, width, height, format,
391                    usage);
392            reply->writeInt32(buf);
393            reply->writeInt32(fence != NULL);
394            if (fence != NULL) {
395                reply->write(*fence);
396            }
397            reply->writeInt32(result);
398            return NO_ERROR;
399        }
400        case DETACH_BUFFER: {
401            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
402            int slot = data.readInt32();
403            int result = detachBuffer(slot);
404            reply->writeInt32(result);
405            return NO_ERROR;
406        }
407        case DETACH_NEXT_BUFFER: {
408            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
409            sp<GraphicBuffer> buffer;
410            sp<Fence> fence;
411            int32_t result = detachNextBuffer(&buffer, &fence);
412            reply->writeInt32(result);
413            if (result == NO_ERROR) {
414                reply->writeInt32(buffer != NULL);
415                if (buffer != NULL) {
416                    reply->write(*buffer);
417                }
418                reply->writeInt32(fence != NULL);
419                if (fence != NULL) {
420                    reply->write(*fence);
421                }
422            }
423            return NO_ERROR;
424        }
425        case ATTACH_BUFFER: {
426            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
427            sp<GraphicBuffer> buffer = new GraphicBuffer();
428            data.read(*buffer.get());
429            int slot = 0;
430            int result = attachBuffer(&slot, buffer);
431            reply->writeInt32(slot);
432            reply->writeInt32(result);
433            return NO_ERROR;
434        }
435        case QUEUE_BUFFER: {
436            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
437            int buf = data.readInt32();
438            QueueBufferInput input(data);
439            QueueBufferOutput* const output =
440                    reinterpret_cast<QueueBufferOutput *>(
441                            reply->writeInplace(sizeof(QueueBufferOutput)));
442            status_t result = queueBuffer(buf, input, output);
443            reply->writeInt32(result);
444            return NO_ERROR;
445        }
446        case CANCEL_BUFFER: {
447            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
448            int buf = data.readInt32();
449            sp<Fence> fence = new Fence();
450            data.read(*fence.get());
451            status_t result = cancelBuffer(buf, fence);
452            reply->writeInt32(result);
453            return NO_ERROR;
454        }
455        case QUERY: {
456            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
457            int value = 0;
458            int what = data.readInt32();
459            int res = query(what, &value);
460            reply->writeInt32(value);
461            reply->writeInt32(res);
462            return NO_ERROR;
463        }
464        case CONNECT: {
465            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
466            sp<IProducerListener> listener;
467            if (data.readInt32() == 1) {
468                listener = IProducerListener::asInterface(data.readStrongBinder());
469            }
470            int api = data.readInt32();
471            bool producerControlledByApp = data.readInt32();
472            QueueBufferOutput* const output =
473                    reinterpret_cast<QueueBufferOutput *>(
474                            reply->writeInplace(sizeof(QueueBufferOutput)));
475            status_t res = connect(listener, api, producerControlledByApp, output);
476            reply->writeInt32(res);
477            return NO_ERROR;
478        }
479        case DISCONNECT: {
480            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
481            int api = data.readInt32();
482            status_t res = disconnect(api);
483            reply->writeInt32(res);
484            return NO_ERROR;
485        }
486        case SET_SIDEBAND_STREAM: {
487            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
488            sp<NativeHandle> stream;
489            if (data.readInt32()) {
490                stream = NativeHandle::create(data.readNativeHandle(), true);
491            }
492            status_t result = setSidebandStream(stream);
493            reply->writeInt32(result);
494            return NO_ERROR;
495        }
496        case ALLOCATE_BUFFERS: {
497            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
498            uint32_t width = data.readUint32();
499            uint32_t height = data.readUint32();
500            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
501            uint32_t usage = data.readUint32();
502            allocateBuffers(width, height, format, usage);
503            return NO_ERROR;
504        }
505        case ALLOW_ALLOCATION: {
506            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
507            bool allow = static_cast<bool>(data.readInt32());
508            status_t result = allowAllocation(allow);
509            reply->writeInt32(result);
510            return NO_ERROR;
511        }
512        case SET_GENERATION_NUMBER: {
513            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
514            uint32_t generationNumber = data.readUint32();
515            status_t result = setGenerationNumber(generationNumber);
516            reply->writeInt32(result);
517            return NO_ERROR;
518        }
519        case GET_CONSUMER_NAME: {
520            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
521            reply->writeString8(getConsumerName());
522            return NO_ERROR;
523        }
524        case GET_NEXT_FRAME_NUMBER: {
525            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
526            uint64_t frameNumber = getNextFrameNumber();
527            reply->writeUint64(frameNumber);
528            return NO_ERROR;
529        }
530    }
531    return BBinder::onTransact(code, data, reply, flags);
532}
533
534// ----------------------------------------------------------------------------
535
536IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
537    parcel.read(*this);
538}
539
540size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
541    return sizeof(timestamp)
542         + sizeof(isAutoTimestamp)
543         + sizeof(dataSpace)
544         + sizeof(crop)
545         + sizeof(scalingMode)
546         + sizeof(transform)
547         + sizeof(stickyTransform)
548         + fence->getFlattenedSize()
549         + surfaceDamage.getFlattenedSize();
550}
551
552size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
553    return fence->getFdCount();
554}
555
556status_t IGraphicBufferProducer::QueueBufferInput::flatten(
557        void*& buffer, size_t& size, int*& fds, size_t& count) const
558{
559    if (size < getFlattenedSize()) {
560        return NO_MEMORY;
561    }
562    FlattenableUtils::write(buffer, size, timestamp);
563    FlattenableUtils::write(buffer, size, isAutoTimestamp);
564    FlattenableUtils::write(buffer, size, dataSpace);
565    FlattenableUtils::write(buffer, size, crop);
566    FlattenableUtils::write(buffer, size, scalingMode);
567    FlattenableUtils::write(buffer, size, transform);
568    FlattenableUtils::write(buffer, size, stickyTransform);
569    status_t result = fence->flatten(buffer, size, fds, count);
570    if (result != NO_ERROR) {
571        return result;
572    }
573    return surfaceDamage.flatten(buffer, size);
574}
575
576status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
577        void const*& buffer, size_t& size, int const*& fds, size_t& count)
578{
579    size_t minNeeded =
580              sizeof(timestamp)
581            + sizeof(isAutoTimestamp)
582            + sizeof(dataSpace)
583            + sizeof(crop)
584            + sizeof(scalingMode)
585            + sizeof(transform)
586            + sizeof(stickyTransform);
587
588    if (size < minNeeded) {
589        return NO_MEMORY;
590    }
591
592    FlattenableUtils::read(buffer, size, timestamp);
593    FlattenableUtils::read(buffer, size, isAutoTimestamp);
594    FlattenableUtils::read(buffer, size, dataSpace);
595    FlattenableUtils::read(buffer, size, crop);
596    FlattenableUtils::read(buffer, size, scalingMode);
597    FlattenableUtils::read(buffer, size, transform);
598    FlattenableUtils::read(buffer, size, stickyTransform);
599
600    fence = new Fence();
601    status_t result = fence->unflatten(buffer, size, fds, count);
602    if (result != NO_ERROR) {
603        return result;
604    }
605    return surfaceDamage.unflatten(buffer, size);
606}
607
608}; // namespace android
609