• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 namespace android {
33 // ----------------------------------------------------------------------------
34 
35 enum {
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 
51 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
52 {
53 public:
BpGraphicBufferProducer(const sp<IBinder> & impl)54     BpGraphicBufferProducer(const sp<IBinder>& impl)
55         : BpInterface<IGraphicBufferProducer>(impl)
56     {
57     }
58 
requestBuffer(int bufferIdx,sp<GraphicBuffer> * buf)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 
setBufferCount(int bufferCount)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 
dequeueBuffer(int * buf,sp<Fence> * fence,bool async,uint32_t w,uint32_t h,uint32_t format,uint32_t usage)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 
detachBuffer(int slot)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 
detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)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 
attachBuffer(int * slot,const sp<GraphicBuffer> & buffer)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 
queueBuffer(int buf,const QueueBufferInput & input,QueueBufferOutput * output)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 
cancelBuffer(int buf,const sp<Fence> & fence)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 
query(int what,int * value)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 
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)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 
disconnect(int api)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 
setSidebandStream(const sp<NativeHandle> & stream)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 
allocateBuffers(bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)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 
273 IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
274 
275 // ----------------------------------------------------------------------
276 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)277 status_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 = 0;
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 = 0;
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 = 0;
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 
QueueBufferInput(const Parcel & parcel)428 IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
429     parcel.read(*this);
430 }
431 
getFlattenedSize() const432 size_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 
getFdCount() const443 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
444     return fence->getFdCount();
445 }
446 
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const447 status_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 
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)463 status_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