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     SET_PARAMETERS,
40     GET_TIMESTAMP,
41     SIGNAL,
42 };
43 
44 class BpAudioTrack : public BpInterface<IAudioTrack>
45 {
46 public:
BpAudioTrack(const sp<IBinder> & impl)47     BpAudioTrack(const sp<IBinder>& impl)
48         : BpInterface<IAudioTrack>(impl)
49     {
50     }
51 
getCblk() const52     virtual sp<IMemory> getCblk() const
53     {
54         Parcel data, reply;
55         sp<IMemory> cblk;
56         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
57         status_t status = remote()->transact(GET_CBLK, data, &reply);
58         if (status == NO_ERROR) {
59             cblk = interface_cast<IMemory>(reply.readStrongBinder());
60             if (cblk != 0 && cblk->pointer() == NULL) {
61                 cblk.clear();
62             }
63         }
64         return cblk;
65     }
66 
start()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 
stop()80     virtual void stop()
81     {
82         Parcel data, reply;
83         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
84         remote()->transact(STOP, data, &reply);
85     }
86 
flush()87     virtual void flush()
88     {
89         Parcel data, reply;
90         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
91         remote()->transact(FLUSH, data, &reply);
92     }
93 
pause()94     virtual void pause()
95     {
96         Parcel data, reply;
97         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
98         remote()->transact(PAUSE, data, &reply);
99     }
100 
attachAuxEffect(int effectId)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 
setParameters(const String8 & keyValuePairs)115     virtual status_t setParameters(const String8& keyValuePairs) {
116         Parcel data, reply;
117         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
118         data.writeString8(keyValuePairs);
119         status_t status = remote()->transact(SET_PARAMETERS, data, &reply);
120         if (status == NO_ERROR) {
121             status = reply.readInt32();
122         }
123         return status;
124     }
125 
getTimestamp(AudioTimestamp & timestamp)126     virtual status_t getTimestamp(AudioTimestamp& timestamp) {
127         Parcel data, reply;
128         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
129         status_t status = remote()->transact(GET_TIMESTAMP, data, &reply);
130         if (status == NO_ERROR) {
131             status = reply.readInt32();
132             if (status == NO_ERROR) {
133                 timestamp.mPosition = reply.readInt32();
134                 timestamp.mTime.tv_sec = reply.readInt32();
135                 timestamp.mTime.tv_nsec = reply.readInt32();
136             }
137         }
138         return status;
139     }
140 
signal()141     virtual void signal() {
142         Parcel data, reply;
143         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
144         remote()->transact(SIGNAL, data, &reply);
145     }
146 };
147 
148 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
149 
150 // ----------------------------------------------------------------------
151 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)152 status_t BnAudioTrack::onTransact(
153     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
154 {
155     switch (code) {
156         case GET_CBLK: {
157             CHECK_INTERFACE(IAudioTrack, data, reply);
158             reply->writeStrongBinder(IInterface::asBinder(getCblk()));
159             return NO_ERROR;
160         } break;
161         case START: {
162             CHECK_INTERFACE(IAudioTrack, data, reply);
163             reply->writeInt32(start());
164             return NO_ERROR;
165         } break;
166         case STOP: {
167             CHECK_INTERFACE(IAudioTrack, data, reply);
168             stop();
169             return NO_ERROR;
170         } break;
171         case FLUSH: {
172             CHECK_INTERFACE(IAudioTrack, data, reply);
173             flush();
174             return NO_ERROR;
175         } break;
176         case PAUSE: {
177             CHECK_INTERFACE(IAudioTrack, data, reply);
178             pause();
179             return NO_ERROR;
180         }
181         case ATTACH_AUX_EFFECT: {
182             CHECK_INTERFACE(IAudioTrack, data, reply);
183             reply->writeInt32(attachAuxEffect(data.readInt32()));
184             return NO_ERROR;
185         } break;
186         case SET_PARAMETERS: {
187             CHECK_INTERFACE(IAudioTrack, data, reply);
188             String8 keyValuePairs(data.readString8());
189             reply->writeInt32(setParameters(keyValuePairs));
190             return NO_ERROR;
191         } break;
192         case GET_TIMESTAMP: {
193             CHECK_INTERFACE(IAudioTrack, data, reply);
194             AudioTimestamp timestamp;
195             status_t status = getTimestamp(timestamp);
196             reply->writeInt32(status);
197             if (status == NO_ERROR) {
198                 reply->writeInt32(timestamp.mPosition);
199                 reply->writeInt32(timestamp.mTime.tv_sec);
200                 reply->writeInt32(timestamp.mTime.tv_nsec);
201             }
202             return NO_ERROR;
203         } break;
204         case SIGNAL: {
205             CHECK_INTERFACE(IAudioTrack, data, reply);
206             signal();
207             return NO_ERROR;
208         } break;
209         default:
210             return BBinder::onTransact(code, data, reply, flags);
211     }
212 }
213 
214 } // namespace android
215