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