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/RefBase.h>
     22 #include <utils/Vector.h>
     23 #include <utils/Timers.h>
     24 
     25 #include <binder/Parcel.h>
     26 #include <binder/IInterface.h>
     27 
     28 #include <gui/IGraphicBufferProducer.h>
     29 
     30 namespace android {
     31 // ----------------------------------------------------------------------------
     32 
     33 enum {
     34     REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
     35     SET_BUFFER_COUNT,
     36     DEQUEUE_BUFFER,
     37     QUEUE_BUFFER,
     38     CANCEL_BUFFER,
     39     QUERY,
     40     SET_SYNCHRONOUS_MODE,
     41     CONNECT,
     42     DISCONNECT,
     43 };
     44 
     45 
     46 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
     47 {
     48 public:
     49     BpGraphicBufferProducer(const sp<IBinder>& impl)
     50         : BpInterface<IGraphicBufferProducer>(impl)
     51     {
     52     }
     53 
     54     virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
     55         Parcel data, reply;
     56         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
     57         data.writeInt32(bufferIdx);
     58         status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
     59         if (result != NO_ERROR) {
     60             return result;
     61         }
     62         bool nonNull = reply.readInt32();
     63         if (nonNull) {
     64             *buf = new GraphicBuffer();
     65             reply.read(**buf);
     66         }
     67         result = reply.readInt32();
     68         return result;
     69     }
     70 
     71     virtual status_t setBufferCount(int bufferCount)
     72     {
     73         Parcel data, reply;
     74         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
     75         data.writeInt32(bufferCount);
     76         status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
     77         if (result != NO_ERROR) {
     78             return result;
     79         }
     80         result = reply.readInt32();
     81         return result;
     82     }
     83 
     84     virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
     85             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
     86         Parcel data, reply;
     87         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
     88         data.writeInt32(w);
     89         data.writeInt32(h);
     90         data.writeInt32(format);
     91         data.writeInt32(usage);
     92         status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
     93         if (result != NO_ERROR) {
     94             return result;
     95         }
     96         *buf = reply.readInt32();
     97         bool fenceWasWritten = reply.readInt32();
     98         if (fenceWasWritten) {
     99             // If the fence was written by the callee, then overwrite the
    100             // caller's fence here.  If it wasn't written then don't touch the
    101             // caller's fence.
    102             *fence = new Fence();
    103             reply.read(*(fence->get()));
    104         }
    105         result = reply.readInt32();
    106         return result;
    107     }
    108 
    109     virtual status_t queueBuffer(int buf,
    110             const QueueBufferInput& input, QueueBufferOutput* output) {
    111         Parcel data, reply;
    112         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
    113         data.writeInt32(buf);
    114         data.write(input);
    115         status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
    116         if (result != NO_ERROR) {
    117             return result;
    118         }
    119         memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
    120         result = reply.readInt32();
    121         return result;
    122     }
    123 
    124     virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
    125         Parcel data, reply;
    126         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
    127         data.writeInt32(buf);
    128         data.write(*fence.get());
    129         remote()->transact(CANCEL_BUFFER, data, &reply);
    130     }
    131 
    132     virtual int query(int what, int* value) {
    133         Parcel data, reply;
    134         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
    135         data.writeInt32(what);
    136         status_t result = remote()->transact(QUERY, data, &reply);
    137         if (result != NO_ERROR) {
    138             return result;
    139         }
    140         value[0] = reply.readInt32();
    141         result = reply.readInt32();
    142         return result;
    143     }
    144 
    145     virtual status_t setSynchronousMode(bool enabled) {
    146         Parcel data, reply;
    147         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
    148         data.writeInt32(enabled);
    149         status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
    150         if (result != NO_ERROR) {
    151             return result;
    152         }
    153         result = reply.readInt32();
    154         return result;
    155     }
    156 
    157     virtual status_t connect(int api, QueueBufferOutput* output) {
    158         Parcel data, reply;
    159         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
    160         data.writeInt32(api);
    161         status_t result = remote()->transact(CONNECT, data, &reply);
    162         if (result != NO_ERROR) {
    163             return result;
    164         }
    165         memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
    166         result = reply.readInt32();
    167         return result;
    168     }
    169 
    170     virtual status_t disconnect(int api) {
    171         Parcel data, reply;
    172         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
    173         data.writeInt32(api);
    174         status_t result =remote()->transact(DISCONNECT, data, &reply);
    175         if (result != NO_ERROR) {
    176             return result;
    177         }
    178         result = reply.readInt32();
    179         return result;
    180     }
    181 };
    182 
    183 IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
    184 
    185 // ----------------------------------------------------------------------
    186 
    187 status_t BnGraphicBufferProducer::onTransact(
    188     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    189 {
    190     switch(code) {
    191         case REQUEST_BUFFER: {
    192             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    193             int bufferIdx   = data.readInt32();
    194             sp<GraphicBuffer> buffer;
    195             int result = requestBuffer(bufferIdx, &buffer);
    196             reply->writeInt32(buffer != 0);
    197             if (buffer != 0) {
    198                 reply->write(*buffer);
    199             }
    200             reply->writeInt32(result);
    201             return NO_ERROR;
    202         } break;
    203         case SET_BUFFER_COUNT: {
    204             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    205             int bufferCount = data.readInt32();
    206             int result = setBufferCount(bufferCount);
    207             reply->writeInt32(result);
    208             return NO_ERROR;
    209         } break;
    210         case DEQUEUE_BUFFER: {
    211             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    212             uint32_t w      = data.readInt32();
    213             uint32_t h      = data.readInt32();
    214             uint32_t format = data.readInt32();
    215             uint32_t usage  = data.readInt32();
    216             int buf;
    217             sp<Fence> fence;
    218             int result = dequeueBuffer(&buf, &fence, w, h, format, usage);
    219             reply->writeInt32(buf);
    220             reply->writeInt32(fence != NULL);
    221             if (fence != NULL) {
    222                 reply->write(*fence.get());
    223             }
    224             reply->writeInt32(result);
    225             return NO_ERROR;
    226         } break;
    227         case QUEUE_BUFFER: {
    228             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    229             int buf = data.readInt32();
    230             QueueBufferInput input(data);
    231             QueueBufferOutput* const output =
    232                     reinterpret_cast<QueueBufferOutput *>(
    233                             reply->writeInplace(sizeof(QueueBufferOutput)));
    234             status_t result = queueBuffer(buf, input, output);
    235             reply->writeInt32(result);
    236             return NO_ERROR;
    237         } break;
    238         case CANCEL_BUFFER: {
    239             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    240             int buf = data.readInt32();
    241             sp<Fence> fence = new Fence();
    242             data.read(*fence.get());
    243             cancelBuffer(buf, fence);
    244             return NO_ERROR;
    245         } break;
    246         case QUERY: {
    247             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    248             int value;
    249             int what = data.readInt32();
    250             int res = query(what, &value);
    251             reply->writeInt32(value);
    252             reply->writeInt32(res);
    253             return NO_ERROR;
    254         } break;
    255         case SET_SYNCHRONOUS_MODE: {
    256             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    257             bool enabled = data.readInt32();
    258             status_t res = setSynchronousMode(enabled);
    259             reply->writeInt32(res);
    260             return NO_ERROR;
    261         } break;
    262         case CONNECT: {
    263             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    264             int api = data.readInt32();
    265             QueueBufferOutput* const output =
    266                     reinterpret_cast<QueueBufferOutput *>(
    267                             reply->writeInplace(sizeof(QueueBufferOutput)));
    268             status_t res = connect(api, output);
    269             reply->writeInt32(res);
    270             return NO_ERROR;
    271         } break;
    272         case DISCONNECT: {
    273             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
    274             int api = data.readInt32();
    275             status_t res = disconnect(api);
    276             reply->writeInt32(res);
    277             return NO_ERROR;
    278         } break;
    279     }
    280     return BBinder::onTransact(code, data, reply, flags);
    281 }
    282 
    283 // ----------------------------------------------------------------------------
    284 
    285 IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
    286     parcel.read(*this);
    287 }
    288 
    289 size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const
    290 {
    291     return sizeof(timestamp)
    292          + sizeof(crop)
    293          + sizeof(scalingMode)
    294          + sizeof(transform)
    295          + fence->getFlattenedSize();
    296 }
    297 
    298 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const
    299 {
    300     return fence->getFdCount();
    301 }
    302 
    303 status_t IGraphicBufferProducer::QueueBufferInput::flatten(void* buffer, size_t size,
    304         int fds[], size_t count) const
    305 {
    306     status_t err = NO_ERROR;
    307     char* p = (char*)buffer;
    308     memcpy(p, &timestamp,   sizeof(timestamp));   p += sizeof(timestamp);
    309     memcpy(p, &crop,        sizeof(crop));        p += sizeof(crop);
    310     memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode);
    311     memcpy(p, &transform,   sizeof(transform));   p += sizeof(transform);
    312     err = fence->flatten(p, size - (p - (char*)buffer), fds, count);
    313     return err;
    314 }
    315 
    316 status_t IGraphicBufferProducer::QueueBufferInput::unflatten(void const* buffer,
    317         size_t size, int fds[], size_t count)
    318 {
    319     status_t err = NO_ERROR;
    320     const char* p = (const char*)buffer;
    321     memcpy(&timestamp,   p, sizeof(timestamp));   p += sizeof(timestamp);
    322     memcpy(&crop,        p, sizeof(crop));        p += sizeof(crop);
    323     memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode);
    324     memcpy(&transform,   p, sizeof(transform));   p += sizeof(transform);
    325     fence = new Fence();
    326     err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count);
    327     return err;
    328 }
    329 
    330 }; // namespace android
    331