Home | History | Annotate | Download | only in libaudioclient
      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 // Maximum command/reply size expected
     29 #define EFFECT_PARAM_SIZE_MAX       65536
     30 
     31 enum {
     32     ENABLE = IBinder::FIRST_CALL_TRANSACTION,
     33     DISABLE,
     34     COMMAND,
     35     DISCONNECT,
     36     GET_CBLK
     37 };
     38 
     39 class BpEffect: public BpInterface<IEffect>
     40 {
     41 public:
     42     explicit BpEffect(const sp<IBinder>& impl)
     43         : BpInterface<IEffect>(impl)
     44     {
     45     }
     46 
     47     status_t enable()
     48     {
     49         ALOGV("enable");
     50         Parcel data, reply;
     51         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
     52         remote()->transact(ENABLE, data, &reply);
     53         return reply.readInt32();
     54     }
     55 
     56     status_t disable()
     57     {
     58         ALOGV("disable");
     59         Parcel data, reply;
     60         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
     61         remote()->transact(DISABLE, data, &reply);
     62         return reply.readInt32();
     63     }
     64 
     65     status_t command(uint32_t cmdCode,
     66                      uint32_t cmdSize,
     67                      void *pCmdData,
     68                      uint32_t *pReplySize,
     69                      void *pReplyData)
     70     {
     71         ALOGV("command");
     72         Parcel data, reply;
     73         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
     74         data.writeInt32(cmdCode);
     75         int size = cmdSize;
     76         if (pCmdData == NULL) {
     77             size = 0;
     78         }
     79         data.writeInt32(size);
     80         if (size) {
     81             data.write(pCmdData, size);
     82         }
     83         if (pReplySize == NULL) {
     84             size = 0;
     85         } else {
     86             size = *pReplySize;
     87         }
     88         data.writeInt32(size);
     89 
     90         status_t status = remote()->transact(COMMAND, data, &reply);
     91         if (status == NO_ERROR) {
     92             status = reply.readInt32();
     93         }
     94         if (status != NO_ERROR) {
     95             if (pReplySize != NULL)
     96                 *pReplySize = 0;
     97             return status;
     98         }
     99 
    100         size = reply.readInt32();
    101         if (size != 0 && pReplyData != NULL && pReplySize != NULL) {
    102             reply.read(pReplyData, size);
    103             *pReplySize = size;
    104         }
    105         return status;
    106     }
    107 
    108     void disconnect()
    109     {
    110         ALOGV("disconnect");
    111         Parcel data, reply;
    112         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
    113         remote()->transact(DISCONNECT, data, &reply);
    114         return;
    115     }
    116 
    117     virtual sp<IMemory> getCblk() const
    118     {
    119         Parcel data, reply;
    120         sp<IMemory> cblk;
    121         data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
    122         status_t status = remote()->transact(GET_CBLK, data, &reply);
    123         if (status == NO_ERROR) {
    124             cblk = interface_cast<IMemory>(reply.readStrongBinder());
    125             if (cblk != 0 && cblk->pointer() == NULL) {
    126                 cblk.clear();
    127             }
    128         }
    129         return cblk;
    130     }
    131  };
    132 
    133 IMPLEMENT_META_INTERFACE(Effect, "android.media.IEffect");
    134 
    135 // ----------------------------------------------------------------------
    136 
    137 status_t BnEffect::onTransact(
    138     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    139 {
    140     switch (code) {
    141         case ENABLE: {
    142             ALOGV("ENABLE");
    143             CHECK_INTERFACE(IEffect, data, reply);
    144             reply->writeInt32(enable());
    145             return NO_ERROR;
    146         } break;
    147 
    148         case DISABLE: {
    149             ALOGV("DISABLE");
    150             CHECK_INTERFACE(IEffect, data, reply);
    151             reply->writeInt32(disable());
    152             return NO_ERROR;
    153         } break;
    154 
    155         case COMMAND: {
    156             ALOGV("COMMAND");
    157             CHECK_INTERFACE(IEffect, data, reply);
    158             uint32_t cmdCode = data.readInt32();
    159             uint32_t cmdSize = data.readInt32();
    160             char *cmd = NULL;
    161             if (cmdSize) {
    162                 if (cmdSize > EFFECT_PARAM_SIZE_MAX) {
    163                     reply->writeInt32(NO_MEMORY);
    164                     return NO_ERROR;
    165                 }
    166                 cmd = (char *)calloc(cmdSize, 1);
    167                 if (cmd == NULL) {
    168                     reply->writeInt32(NO_MEMORY);
    169                     return NO_ERROR;
    170                 }
    171                 data.read(cmd, cmdSize);
    172             }
    173             uint32_t replySize = data.readInt32();
    174             uint32_t replySz = replySize;
    175             char *resp = NULL;
    176             if (replySize) {
    177                 if (replySize > EFFECT_PARAM_SIZE_MAX) {
    178                     free(cmd);
    179                     reply->writeInt32(NO_MEMORY);
    180                     return NO_ERROR;
    181                 }
    182                 resp = (char *)calloc(replySize, 1);
    183                 if (resp == NULL) {
    184                     free(cmd);
    185                     reply->writeInt32(NO_MEMORY);
    186                     return NO_ERROR;
    187                 }
    188             }
    189             status_t status = command(cmdCode, cmdSize, cmd, &replySz, resp);
    190             reply->writeInt32(status);
    191             if (status == NO_ERROR) {
    192                 if (replySz < replySize) {
    193                     replySize = replySz;
    194                 }
    195                 reply->writeInt32(replySize);
    196                 if (replySize) {
    197                     reply->write(resp, replySize);
    198                 }
    199             }
    200             if (cmd) {
    201                 free(cmd);
    202             }
    203             if (resp) {
    204                 free(resp);
    205             }
    206             return NO_ERROR;
    207         } break;
    208 
    209         case DISCONNECT: {
    210             ALOGV("DISCONNECT");
    211             CHECK_INTERFACE(IEffect, data, reply);
    212             disconnect();
    213             return NO_ERROR;
    214         } break;
    215 
    216         case GET_CBLK: {
    217             CHECK_INTERFACE(IEffect, data, reply);
    218             reply->writeStrongBinder(IInterface::asBinder(getCblk()));
    219             return NO_ERROR;
    220         } break;
    221 
    222         default:
    223             return BBinder::onTransact(code, data, reply, flags);
    224     }
    225 }
    226 
    227 // ----------------------------------------------------------------------------
    228 
    229 } // namespace android
    230