• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     APPLY_VOLUME_SHAPER,
43     GET_VOLUME_SHAPER_STATE,
44 };
45 
46 class BpAudioTrack : public BpInterface<IAudioTrack>
47 {
48 public:
BpAudioTrack(const sp<IBinder> & impl)49     explicit BpAudioTrack(const sp<IBinder>& impl)
50         : BpInterface<IAudioTrack>(impl)
51     {
52     }
53 
getCblk() const54     virtual sp<IMemory> getCblk() const
55     {
56         Parcel data, reply;
57         sp<IMemory> cblk;
58         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
59         status_t status = remote()->transact(GET_CBLK, data, &reply);
60         if (status == NO_ERROR) {
61             cblk = interface_cast<IMemory>(reply.readStrongBinder());
62             if (cblk != 0 && cblk->pointer() == NULL) {
63                 cblk.clear();
64             }
65         }
66         return cblk;
67     }
68 
start()69     virtual status_t start()
70     {
71         Parcel data, reply;
72         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
73         status_t status = remote()->transact(START, data, &reply);
74         if (status == NO_ERROR) {
75             status = reply.readInt32();
76         } else {
77             ALOGW("start() error: %s", strerror(-status));
78         }
79         return status;
80     }
81 
stop()82     virtual void stop()
83     {
84         Parcel data, reply;
85         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
86         remote()->transact(STOP, data, &reply);
87     }
88 
flush()89     virtual void flush()
90     {
91         Parcel data, reply;
92         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
93         remote()->transact(FLUSH, data, &reply);
94     }
95 
pause()96     virtual void pause()
97     {
98         Parcel data, reply;
99         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
100         remote()->transact(PAUSE, data, &reply);
101     }
102 
attachAuxEffect(int effectId)103     virtual status_t attachAuxEffect(int effectId)
104     {
105         Parcel data, reply;
106         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
107         data.writeInt32(effectId);
108         status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
109         if (status == NO_ERROR) {
110             status = reply.readInt32();
111         } else {
112             ALOGW("attachAuxEffect() error: %s", strerror(-status));
113         }
114         return status;
115     }
116 
setParameters(const String8 & keyValuePairs)117     virtual status_t setParameters(const String8& keyValuePairs) {
118         Parcel data, reply;
119         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
120         data.writeString8(keyValuePairs);
121         status_t status = remote()->transact(SET_PARAMETERS, data, &reply);
122         if (status == NO_ERROR) {
123             status = reply.readInt32();
124         }
125         return status;
126     }
127 
getTimestamp(AudioTimestamp & timestamp)128     virtual status_t getTimestamp(AudioTimestamp& timestamp) {
129         Parcel data, reply;
130         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
131         status_t status = remote()->transact(GET_TIMESTAMP, data, &reply);
132         if (status == NO_ERROR) {
133             status = reply.readInt32();
134             if (status == NO_ERROR) {
135                 timestamp.mPosition = reply.readInt32();
136                 timestamp.mTime.tv_sec = reply.readInt32();
137                 timestamp.mTime.tv_nsec = reply.readInt32();
138             }
139         }
140         return status;
141     }
142 
signal()143     virtual void signal() {
144         Parcel data, reply;
145         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
146         remote()->transact(SIGNAL, data, &reply);
147     }
148 
applyVolumeShaper(const sp<VolumeShaper::Configuration> & configuration,const sp<VolumeShaper::Operation> & operation)149     virtual VolumeShaper::Status applyVolumeShaper(
150             const sp<VolumeShaper::Configuration>& configuration,
151             const sp<VolumeShaper::Operation>& operation) {
152         Parcel data, reply;
153         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
154 
155         status_t status = configuration.get() == nullptr
156                 ? data.writeInt32(0)
157                 :  data.writeInt32(1)
158                     ?: configuration->writeToParcel(&data);
159         if (status != NO_ERROR) {
160             return VolumeShaper::Status(status);
161         }
162 
163         status = operation.get() == nullptr
164                 ? status = data.writeInt32(0)
165                 : data.writeInt32(1)
166                     ?: operation->writeToParcel(&data);
167         if (status != NO_ERROR) {
168             return VolumeShaper::Status(status);
169         }
170 
171         int32_t remoteVolumeShaperStatus;
172         status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply)
173                  ?: reply.readInt32(&remoteVolumeShaperStatus);
174 
175         return VolumeShaper::Status(status ?: remoteVolumeShaperStatus);
176     }
177 
getVolumeShaperState(int id)178     virtual sp<VolumeShaper::State> getVolumeShaperState(int id) {
179         Parcel data, reply;
180         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
181 
182         data.writeInt32(id);
183         status_t status = remote()->transact(GET_VOLUME_SHAPER_STATE, data, &reply);
184         if (status != NO_ERROR) {
185             return nullptr;
186         }
187         sp<VolumeShaper::State> state = new VolumeShaper::State;
188         status = state->readFromParcel(reply);
189         if (status != NO_ERROR) {
190             return nullptr;
191         }
192         return state;
193     }
194 };
195 
196 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
197 
198 // ----------------------------------------------------------------------
199 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)200 status_t BnAudioTrack::onTransact(
201     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
202 {
203     switch (code) {
204         case GET_CBLK: {
205             CHECK_INTERFACE(IAudioTrack, data, reply);
206             reply->writeStrongBinder(IInterface::asBinder(getCblk()));
207             return NO_ERROR;
208         } break;
209         case START: {
210             CHECK_INTERFACE(IAudioTrack, data, reply);
211             reply->writeInt32(start());
212             return NO_ERROR;
213         } break;
214         case STOP: {
215             CHECK_INTERFACE(IAudioTrack, data, reply);
216             stop();
217             return NO_ERROR;
218         } break;
219         case FLUSH: {
220             CHECK_INTERFACE(IAudioTrack, data, reply);
221             flush();
222             return NO_ERROR;
223         } break;
224         case PAUSE: {
225             CHECK_INTERFACE(IAudioTrack, data, reply);
226             pause();
227             return NO_ERROR;
228         }
229         case ATTACH_AUX_EFFECT: {
230             CHECK_INTERFACE(IAudioTrack, data, reply);
231             reply->writeInt32(attachAuxEffect(data.readInt32()));
232             return NO_ERROR;
233         } break;
234         case SET_PARAMETERS: {
235             CHECK_INTERFACE(IAudioTrack, data, reply);
236             String8 keyValuePairs(data.readString8());
237             reply->writeInt32(setParameters(keyValuePairs));
238             return NO_ERROR;
239         } break;
240         case GET_TIMESTAMP: {
241             CHECK_INTERFACE(IAudioTrack, data, reply);
242             AudioTimestamp timestamp;
243             status_t status = getTimestamp(timestamp);
244             reply->writeInt32(status);
245             if (status == NO_ERROR) {
246                 reply->writeInt32(timestamp.mPosition);
247                 reply->writeInt32(timestamp.mTime.tv_sec);
248                 reply->writeInt32(timestamp.mTime.tv_nsec);
249             }
250             return NO_ERROR;
251         } break;
252         case SIGNAL: {
253             CHECK_INTERFACE(IAudioTrack, data, reply);
254             signal();
255             return NO_ERROR;
256         } break;
257         case APPLY_VOLUME_SHAPER: {
258             CHECK_INTERFACE(IAudioTrack, data, reply);
259             sp<VolumeShaper::Configuration> configuration;
260             sp<VolumeShaper::Operation> operation;
261 
262             int32_t present;
263             status_t status = data.readInt32(&present);
264             if (status == NO_ERROR && present != 0) {
265                 configuration = new VolumeShaper::Configuration();
266                 status = configuration->readFromParcel(data);
267             }
268             status = status ?: data.readInt32(&present);
269             if (status == NO_ERROR && present != 0) {
270                 operation = new VolumeShaper::Operation();
271                 status = operation->readFromParcel(data);
272             }
273             if (status == NO_ERROR) {
274                 status = (status_t)applyVolumeShaper(configuration, operation);
275             }
276             reply->writeInt32(status);
277             return NO_ERROR;
278         } break;
279         case GET_VOLUME_SHAPER_STATE: {
280             CHECK_INTERFACE(IAudioTrack, data, reply);
281             int id;
282             status_t status = data.readInt32(&id);
283             if (status == NO_ERROR) {
284                 sp<VolumeShaper::State> state = getVolumeShaperState(id);
285                 if (state.get() != nullptr) {
286                      status = state->writeToParcel(reply);
287                 }
288             }
289             return NO_ERROR;
290         } break;
291         default:
292             return BBinder::onTransact(code, data, reply, flags);
293     }
294 }
295 
296 } // namespace android
297