1 /*
2 **
3 ** Copyright 2007, 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_TAG "IAudioTrack"
19 //#define LOG_NDEBUG 0
20 #include <utils/Log.h>
21 
22 #include <stdint.h>
23 #include <sys/types.h>
24 
25 #include <binder/Parcel.h>
26 
27 #include <media/IAudioTrack.h>
28 
29 namespace android {
30 
31 enum {
32     GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
33     START,
34     STOP,
35     FLUSH,
36     RESERVED, // was MUTE
37     PAUSE,
38     ATTACH_AUX_EFFECT,
39     ALLOCATE_TIMED_BUFFER,
40     QUEUE_TIMED_BUFFER,
41     SET_MEDIA_TIME_TRANSFORM,
42     SET_PARAMETERS,
43     GET_TIMESTAMP,
44     SIGNAL,
45 };
46 
47 class BpAudioTrack : public BpInterface<IAudioTrack>
48 {
49 public:
BpAudioTrack(const sp<IBinder> & impl)50     BpAudioTrack(const sp<IBinder>& impl)
51         : BpInterface<IAudioTrack>(impl)
52     {
53     }
54 
getCblk() const55     virtual sp<IMemory> getCblk() const
56     {
57         Parcel data, reply;
58         sp<IMemory> cblk;
59         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
60         status_t status = remote()->transact(GET_CBLK, data, &reply);
61         if (status == NO_ERROR) {
62             cblk = interface_cast<IMemory>(reply.readStrongBinder());
63             if (cblk != 0 && cblk->pointer() == NULL) {
64                 cblk.clear();
65             }
66         }
67         return cblk;
68     }
69 
start()70     virtual status_t start()
71     {
72         Parcel data, reply;
73         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
74         status_t status = remote()->transact(START, data, &reply);
75         if (status == NO_ERROR) {
76             status = reply.readInt32();
77         } else {
78             ALOGW("start() error: %s", strerror(-status));
79         }
80         return status;
81     }
82 
stop()83     virtual void stop()
84     {
85         Parcel data, reply;
86         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
87         remote()->transact(STOP, data, &reply);
88     }
89 
flush()90     virtual void flush()
91     {
92         Parcel data, reply;
93         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
94         remote()->transact(FLUSH, data, &reply);
95     }
96 
pause()97     virtual void pause()
98     {
99         Parcel data, reply;
100         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
101         remote()->transact(PAUSE, data, &reply);
102     }
103 
attachAuxEffect(int effectId)104     virtual status_t attachAuxEffect(int effectId)
105     {
106         Parcel data, reply;
107         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
108         data.writeInt32(effectId);
109         status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
110         if (status == NO_ERROR) {
111             status = reply.readInt32();
112         } else {
113             ALOGW("attachAuxEffect() error: %s", strerror(-status));
114         }
115         return status;
116     }
117 
allocateTimedBuffer(size_t size,sp<IMemory> * buffer)118     virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) {
119         Parcel data, reply;
120         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
121         data.writeInt64(size);
122         status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER,
123                                              data, &reply);
124         if (status == NO_ERROR) {
125             status = reply.readInt32();
126             if (status == NO_ERROR) {
127                 *buffer = interface_cast<IMemory>(reply.readStrongBinder());
128                 if (*buffer != 0 && (*buffer)->pointer() == NULL) {
129                     (*buffer).clear();
130                 }
131             }
132         }
133         return status;
134     }
135 
queueTimedBuffer(const sp<IMemory> & buffer,int64_t pts)136     virtual status_t queueTimedBuffer(const sp<IMemory>& buffer,
137                                       int64_t pts) {
138         Parcel data, reply;
139         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
140         data.writeStrongBinder(IInterface::asBinder(buffer));
141         data.writeInt64(pts);
142         status_t status = remote()->transact(QUEUE_TIMED_BUFFER,
143                                              data, &reply);
144         if (status == NO_ERROR) {
145             status = reply.readInt32();
146         }
147         return status;
148     }
149 
setMediaTimeTransform(const LinearTransform & xform,int target)150     virtual status_t setMediaTimeTransform(const LinearTransform& xform,
151                                            int target) {
152         Parcel data, reply;
153         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
154         data.writeInt64(xform.a_zero);
155         data.writeInt64(xform.b_zero);
156         data.writeInt32(xform.a_to_b_numer);
157         data.writeInt32(xform.a_to_b_denom);
158         data.writeInt32(target);
159         status_t status = remote()->transact(SET_MEDIA_TIME_TRANSFORM,
160                                              data, &reply);
161         if (status == NO_ERROR) {
162             status = reply.readInt32();
163         }
164         return status;
165     }
166 
setParameters(const String8 & keyValuePairs)167     virtual status_t setParameters(const String8& keyValuePairs) {
168         Parcel data, reply;
169         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
170         data.writeString8(keyValuePairs);
171         status_t status = remote()->transact(SET_PARAMETERS, data, &reply);
172         if (status == NO_ERROR) {
173             status = reply.readInt32();
174         }
175         return status;
176     }
177 
getTimestamp(AudioTimestamp & timestamp)178     virtual status_t getTimestamp(AudioTimestamp& timestamp) {
179         Parcel data, reply;
180         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
181         status_t status = remote()->transact(GET_TIMESTAMP, data, &reply);
182         if (status == NO_ERROR) {
183             status = reply.readInt32();
184             if (status == NO_ERROR) {
185                 timestamp.mPosition = reply.readInt32();
186                 timestamp.mTime.tv_sec = reply.readInt32();
187                 timestamp.mTime.tv_nsec = reply.readInt32();
188             }
189         }
190         return status;
191     }
192 
signal()193     virtual void signal() {
194         Parcel data, reply;
195         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
196         remote()->transact(SIGNAL, data, &reply);
197     }
198 };
199 
200 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
201 
202 // ----------------------------------------------------------------------
203 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)204 status_t BnAudioTrack::onTransact(
205     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
206 {
207     switch (code) {
208         case GET_CBLK: {
209             CHECK_INTERFACE(IAudioTrack, data, reply);
210             reply->writeStrongBinder(IInterface::asBinder(getCblk()));
211             return NO_ERROR;
212         } break;
213         case START: {
214             CHECK_INTERFACE(IAudioTrack, data, reply);
215             reply->writeInt32(start());
216             return NO_ERROR;
217         } break;
218         case STOP: {
219             CHECK_INTERFACE(IAudioTrack, data, reply);
220             stop();
221             return NO_ERROR;
222         } break;
223         case FLUSH: {
224             CHECK_INTERFACE(IAudioTrack, data, reply);
225             flush();
226             return NO_ERROR;
227         } break;
228         case PAUSE: {
229             CHECK_INTERFACE(IAudioTrack, data, reply);
230             pause();
231             return NO_ERROR;
232         }
233         case ATTACH_AUX_EFFECT: {
234             CHECK_INTERFACE(IAudioTrack, data, reply);
235             reply->writeInt32(attachAuxEffect(data.readInt32()));
236             return NO_ERROR;
237         } break;
238         case ALLOCATE_TIMED_BUFFER: {
239             CHECK_INTERFACE(IAudioTrack, data, reply);
240             sp<IMemory> buffer;
241             status_t status = allocateTimedBuffer(data.readInt64(), &buffer);
242             reply->writeInt32(status);
243             if (status == NO_ERROR) {
244                 reply->writeStrongBinder(IInterface::asBinder(buffer));
245             }
246             return NO_ERROR;
247         } break;
248         case QUEUE_TIMED_BUFFER: {
249             CHECK_INTERFACE(IAudioTrack, data, reply);
250             sp<IMemory> buffer = interface_cast<IMemory>(
251                 data.readStrongBinder());
252             uint64_t pts = data.readInt64();
253             reply->writeInt32(queueTimedBuffer(buffer, pts));
254             return NO_ERROR;
255         } break;
256         case SET_MEDIA_TIME_TRANSFORM: {
257             CHECK_INTERFACE(IAudioTrack, data, reply);
258             LinearTransform xform;
259             xform.a_zero = data.readInt64();
260             xform.b_zero = data.readInt64();
261             xform.a_to_b_numer = data.readInt32();
262             xform.a_to_b_denom = data.readInt32();
263             int target = data.readInt32();
264             reply->writeInt32(setMediaTimeTransform(xform, target));
265             return NO_ERROR;
266         } break;
267         case SET_PARAMETERS: {
268             CHECK_INTERFACE(IAudioTrack, data, reply);
269             String8 keyValuePairs(data.readString8());
270             reply->writeInt32(setParameters(keyValuePairs));
271             return NO_ERROR;
272         } break;
273         case GET_TIMESTAMP: {
274             CHECK_INTERFACE(IAudioTrack, data, reply);
275             AudioTimestamp timestamp;
276             status_t status = getTimestamp(timestamp);
277             reply->writeInt32(status);
278             if (status == NO_ERROR) {
279                 reply->writeInt32(timestamp.mPosition);
280                 reply->writeInt32(timestamp.mTime.tv_sec);
281                 reply->writeInt32(timestamp.mTime.tv_nsec);
282             }
283             return NO_ERROR;
284         } break;
285         case SIGNAL: {
286             CHECK_INTERFACE(IAudioTrack, data, reply);
287             signal();
288             return NO_ERROR;
289         } break;
290         default:
291             return BBinder::onTransact(code, data, reply, flags);
292     }
293 }
294 
295 } // namespace android
296