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