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:
BpEffect(const sp<IBinder> & impl)42     explicit BpEffect(const sp<IBinder>& impl)
43         : BpInterface<IEffect>(impl)
44     {
45     }
46 
enable()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 
disable()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 
command(uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * pReplySize,void * pReplyData)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 
disconnect()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 
getCblk() const117     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 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)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