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