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