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 26namespace android { 27 28// Maximum command/reply size expected 29#define EFFECT_PARAM_SIZE_MAX 65536 30 31enum { 32 ENABLE = IBinder::FIRST_CALL_TRANSACTION, 33 DISABLE, 34 COMMAND, 35 DISCONNECT, 36 GET_CBLK 37}; 38 39class BpEffect: public BpInterface<IEffect> 40{ 41public: 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 133IMPLEMENT_META_INTERFACE(Effect, "android.media.IEffect"); 134 135// ---------------------------------------------------------------------- 136 137status_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