Home | History | Annotate | Download | only in gui
      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:
     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 
    273 IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
    274 
    275 // ----------------------------------------------------------------------
    276 
    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;
    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 
    428 IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
    429     parcel.read(*this);
    430 }
    431 
    432 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 
    443 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
    444     return fence->getFdCount();
    445 }
    446 
    447 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 
    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