Home | History | Annotate | Download | only in libmedia
      1 /*
      2 **
      3 ** Copyright 2010, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 //#define LOG_NDEBUG 0
     19 #define LOG_TAG "IEffect"
     20 #include <utils/Log.h>
     21 #include <stdint.h>
     22 #include <sys/types.h>
     23 #include <binder/Parcel.h>
     24 #include <media/IEffect.h>
     25 
     26 namespace android {
     27 
     28 enum {
     29     ENABLE = IBinder::FIRST_CALL_TRANSACTION,
     30     DISABLE,
     31     COMMAND,
     32     DISCONNECT,
     33     GET_CBLK
     34 };
     35 
     36 class BpEffect: public BpInterface<IEffect>
     37 {
     38 public:
     39     BpEffect(const sp<IBinder>& impl)
     40         : BpInterface<IEffect>(impl)
     41     {
     42     }
     43 
     44     status_t enable()
     45     {
     46         ALOGV("enable");
     47         Parcel data, reply;
     48         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
     49         remote()->transact(ENABLE, data, &reply);
     50         return reply.readInt32();
     51     }
     52 
     53     status_t disable()
     54     {
     55         ALOGV("disable");
     56         Parcel data, reply;
     57         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
     58         remote()->transact(DISABLE, data, &reply);
     59         return reply.readInt32();
     60     }
     61 
     62     status_t command(uint32_t cmdCode,
     63                      uint32_t cmdSize,
     64                      void *pCmdData,
     65                      uint32_t *pReplySize,
     66                      void *pReplyData)
     67     {
     68         ALOGV("command");
     69         Parcel data, reply;
     70         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
     71         data.writeInt32(cmdCode);
     72         int size = cmdSize;
     73         if (pCmdData == NULL) {
     74             size = 0;
     75         }
     76         data.writeInt32(size);
     77         if (size) {
     78             data.write(pCmdData, size);
     79         }
     80         if (pReplySize == NULL) {
     81             size = 0;
     82         } else {
     83             size = *pReplySize;
     84         }
     85         data.writeInt32(size);
     86 
     87         status_t status = remote()->transact(COMMAND, data, &reply);
     88         if (status == NO_ERROR) {
     89             status = reply.readInt32();
     90         }
     91         if (status != NO_ERROR) {
     92             if (pReplySize != NULL)
     93                 *pReplySize = 0;
     94             return status;
     95         }
     96 
     97         size = reply.readInt32();
     98         if (size != 0 && pReplyData != NULL && pReplySize != NULL) {
     99             reply.read(pReplyData, size);
    100             *pReplySize = size;
    101         }
    102         return status;
    103     }
    104 
    105     void disconnect()
    106     {
    107         ALOGV("disconnect");
    108         Parcel data, reply;
    109         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
    110         remote()->transact(DISCONNECT, data, &reply);
    111         return;
    112     }
    113 
    114     virtual sp<IMemory> getCblk() const
    115     {
    116         Parcel data, reply;
    117         sp<IMemory> cblk;
    118         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
    119         status_t status = remote()->transact(GET_CBLK, data, &reply);
    120         if (status == NO_ERROR) {
    121             cblk = interface_cast<IMemory>(reply.readStrongBinder());
    122             if (cblk != 0 && cblk->pointer() == NULL) {
    123                 cblk.clear();
    124             }
    125         }
    126         return cblk;
    127     }
    128  };
    129 
    130 IMPLEMENT_META_INTERFACE(Effect, "android.media.IEffect");
    131 
    132 // ----------------------------------------------------------------------
    133 
    134 status_t BnEffect::onTransact(
    135     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    136 {
    137     switch (code) {
    138         case ENABLE: {
    139             ALOGV("ENABLE");
    140             CHECK_INTERFACE(IEffect, data, reply);
    141             reply->writeInt32(enable());
    142             return NO_ERROR;
    143         } break;
    144 
    145         case DISABLE: {
    146             ALOGV("DISABLE");
    147             CHECK_INTERFACE(IEffect, data, reply);
    148             reply->writeInt32(disable());
    149             return NO_ERROR;
    150         } break;
    151 
    152         case COMMAND: {
    153             ALOGV("COMMAND");
    154             CHECK_INTERFACE(IEffect, data, reply);
    155             uint32_t cmdCode = data.readInt32();
    156             uint32_t cmdSize = data.readInt32();
    157             char *cmd = NULL;
    158             if (cmdSize) {
    159                 cmd = (char *)calloc(cmdSize, 1);
    160                 if (cmd == NULL) {
    161                     reply->writeInt32(NO_MEMORY);
    162                     return NO_ERROR;
    163                 }
    164                 data.read(cmd, cmdSize);
    165             }
    166             uint32_t replySize = data.readInt32();
    167             uint32_t replySz = replySize;
    168             char *resp = NULL;
    169             if (replySize) {
    170                 resp = (char *)calloc(replySize, 1);
    171                 if (resp == NULL) {
    172                     free(cmd);
    173                     reply->writeInt32(NO_MEMORY);
    174                     return NO_ERROR;
    175                 }
    176             }
    177             status_t status = command(cmdCode, cmdSize, cmd, &replySz, resp);
    178             reply->writeInt32(status);
    179             if (status == NO_ERROR) {
    180                 if (replySz < replySize) {
    181                     replySize = replySz;
    182                 }
    183                 reply->writeInt32(replySize);
    184                 if (replySize) {
    185                     reply->write(resp, replySize);
    186                 }
    187             }
    188             if (cmd) {
    189                 free(cmd);
    190             }
    191             if (resp) {
    192                 free(resp);
    193             }
    194             return NO_ERROR;
    195         } break;
    196 
    197         case DISCONNECT: {
    198             ALOGV("DISCONNECT");
    199             CHECK_INTERFACE(IEffect, data, reply);
    200             disconnect();
    201             return NO_ERROR;
    202         } break;
    203 
    204         case GET_CBLK: {
    205             CHECK_INTERFACE(IEffect, data, reply);
    206             reply->writeStrongBinder(IInterface::asBinder(getCblk()));
    207             return NO_ERROR;
    208         } break;
    209 
    210         default:
    211             return BBinder::onTransact(code, data, reply, flags);
    212     }
    213 }
    214 
    215 // ----------------------------------------------------------------------------
    216 
    217 } // namespace android
    218