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