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