blob: 6fcf3002471bf33de81eb6ade590a403e122835f [file] [log] [blame]
Glenn Kasten99e53b82012-01-19 08:59:58 -08001/*
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08002**
3** Copyright 2007, The Android Open Source Project
4**
Glenn Kastene53b9ea2012-03-12 16:29:55 -07005** 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
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08008**
Glenn Kastene53b9ea2012-03-12 16:29:55 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080010**
Glenn Kastene53b9ea2012-03-12 16:29:55 -070011** 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
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
Eric Laurent34f1d8e2009-11-04 08:27:26 -080018#define LOG_TAG "IAudioTrack"
19//#define LOG_NDEBUG 0
20#include <utils/Log.h>
21
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080022#include <stdint.h>
23#include <sys/types.h>
24
Mathias Agopian75624082009-05-19 19:08:10 -070025#include <binder/Parcel.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080026
27#include <media/IAudioTrack.h>
28
29namespace android {
30
Ivan Lozano8cf3a072017-08-09 09:01:33 -070031using media::VolumeShaper;
32
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080033enum {
34 GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
35 START,
36 STOP,
37 FLUSH,
Glenn Kastene4756fe2012-11-29 13:38:14 -080038 RESERVED, // was MUTE
Eric Laurentbe916aa2010-06-01 23:49:17 -070039 PAUSE,
John Grossman4ff14ba2012-02-08 16:37:41 -080040 ATTACH_AUX_EFFECT,
Glenn Kasten53cec222013-08-29 09:01:02 -070041 SET_PARAMETERS,
Mikhail Naganovac917ac2018-11-28 14:03:52 -080042 SELECT_PRESENTATION,
Glenn Kasten53cec222013-08-29 09:01:02 -070043 GET_TIMESTAMP,
Eric Laurent59fe0102013-09-27 18:48:26 -070044 SIGNAL,
Andy Hung9fc8b5c2017-01-24 13:36:48 -080045 APPLY_VOLUME_SHAPER,
46 GET_VOLUME_SHAPER_STATE,
Kuowei Li3bea3a42020-08-13 14:44:25 +080047 SET_DUAL_MONO_MODE,
48 GET_DUAL_MONO_MODE,
49 SET_AUDIO_DESCRIPTION_MIX_LEVEL,
50 GET_AUDIO_DESCRIPTION_MIX_LEVEL,
51 SET_PLAYBACK_RATE_PARAMETERS,
52 GET_PLAYBACK_RATE_PARAMETERS,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080053};
54
55class BpAudioTrack : public BpInterface<IAudioTrack>
56{
57public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070058 explicit BpAudioTrack(const sp<IBinder>& impl)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080059 : BpInterface<IAudioTrack>(impl)
60 {
61 }
Glenn Kastene53b9ea2012-03-12 16:29:55 -070062
Glenn Kasten10995862012-01-03 14:50:23 -080063 virtual sp<IMemory> getCblk() const
64 {
65 Parcel data, reply;
66 sp<IMemory> cblk;
67 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
68 status_t status = remote()->transact(GET_CBLK, data, &reply);
69 if (status == NO_ERROR) {
70 cblk = interface_cast<IMemory>(reply.readStrongBinder());
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -070071 if (cblk != 0 && cblk->unsecurePointer() == NULL) {
Glenn Kastena1d401d2013-11-20 14:37:13 -080072 cblk.clear();
73 }
Glenn Kasten10995862012-01-03 14:50:23 -080074 }
75 return cblk;
76 }
77
Glenn Kasten3acbd052012-02-28 10:39:56 -080078 virtual status_t start()
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080079 {
80 Parcel data, reply;
81 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
Eric Laurent34f1d8e2009-11-04 08:27:26 -080082 status_t status = remote()->transact(START, data, &reply);
83 if (status == NO_ERROR) {
84 status = reply.readInt32();
85 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +000086 ALOGW("start() error: %s", strerror(-status));
Eric Laurent34f1d8e2009-11-04 08:27:26 -080087 }
88 return status;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080089 }
Glenn Kastene53b9ea2012-03-12 16:29:55 -070090
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080091 virtual void stop()
92 {
93 Parcel data, reply;
94 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
95 remote()->transact(STOP, data, &reply);
96 }
Glenn Kastene53b9ea2012-03-12 16:29:55 -070097
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080098 virtual void flush()
99 {
100 Parcel data, reply;
101 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
102 remote()->transact(FLUSH, data, &reply);
103 }
104
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800105 virtual void pause()
106 {
107 Parcel data, reply;
108 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
109 remote()->transact(PAUSE, data, &reply);
110 }
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700111
Eric Laurentbe916aa2010-06-01 23:49:17 -0700112 virtual status_t attachAuxEffect(int effectId)
113 {
114 Parcel data, reply;
115 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
116 data.writeInt32(effectId);
117 status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
118 if (status == NO_ERROR) {
119 status = reply.readInt32();
120 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +0000121 ALOGW("attachAuxEffect() error: %s", strerror(-status));
Eric Laurentbe916aa2010-06-01 23:49:17 -0700122 }
123 return status;
124 }
John Grossman4ff14ba2012-02-08 16:37:41 -0800125
Richard Fitzgeraldad3af332013-03-25 16:54:37 +0000126 virtual status_t setParameters(const String8& keyValuePairs) {
127 Parcel data, reply;
128 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
129 data.writeString8(keyValuePairs);
130 status_t status = remote()->transact(SET_PARAMETERS, data, &reply);
131 if (status == NO_ERROR) {
132 status = reply.readInt32();
133 }
134 return status;
135 }
Glenn Kasten53cec222013-08-29 09:01:02 -0700136
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800137 /* Selects the presentation (if available) */
138 virtual status_t selectPresentation(int presentationId, int programId) {
139 Parcel data, reply;
140 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
141 data.writeInt32(presentationId);
142 data.writeInt32(programId);
143 status_t status = remote()->transact(SELECT_PRESENTATION, data, &reply);
144 if (status == NO_ERROR) {
145 status = reply.readInt32();
146 }
147 return status;
148 }
149
Glenn Kasten53cec222013-08-29 09:01:02 -0700150 virtual status_t getTimestamp(AudioTimestamp& timestamp) {
151 Parcel data, reply;
152 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
153 status_t status = remote()->transact(GET_TIMESTAMP, data, &reply);
154 if (status == NO_ERROR) {
155 status = reply.readInt32();
156 if (status == NO_ERROR) {
157 timestamp.mPosition = reply.readInt32();
158 timestamp.mTime.tv_sec = reply.readInt32();
159 timestamp.mTime.tv_nsec = reply.readInt32();
160 }
161 }
162 return status;
163 }
Eric Laurent59fe0102013-09-27 18:48:26 -0700164
165 virtual void signal() {
166 Parcel data, reply;
167 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
168 remote()->transact(SIGNAL, data, &reply);
169 }
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800170
171 virtual VolumeShaper::Status applyVolumeShaper(
172 const sp<VolumeShaper::Configuration>& configuration,
173 const sp<VolumeShaper::Operation>& operation) {
174 Parcel data, reply;
175 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
176
177 status_t status = configuration.get() == nullptr
178 ? data.writeInt32(0)
179 : data.writeInt32(1)
180 ?: configuration->writeToParcel(&data);
181 if (status != NO_ERROR) {
182 return VolumeShaper::Status(status);
183 }
184
185 status = operation.get() == nullptr
186 ? status = data.writeInt32(0)
187 : data.writeInt32(1)
188 ?: operation->writeToParcel(&data);
189 if (status != NO_ERROR) {
190 return VolumeShaper::Status(status);
191 }
192
193 int32_t remoteVolumeShaperStatus;
194 status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply)
195 ?: reply.readInt32(&remoteVolumeShaperStatus);
196
197 return VolumeShaper::Status(status ?: remoteVolumeShaperStatus);
198 }
199
200 virtual sp<VolumeShaper::State> getVolumeShaperState(int id) {
201 Parcel data, reply;
202 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
203
204 data.writeInt32(id);
205 status_t status = remote()->transact(GET_VOLUME_SHAPER_STATE, data, &reply);
206 if (status != NO_ERROR) {
207 return nullptr;
208 }
209 sp<VolumeShaper::State> state = new VolumeShaper::State;
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700210 status = state->readFromParcel(&reply);
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800211 if (status != NO_ERROR) {
212 return nullptr;
213 }
214 return state;
215 }
Kuowei Li3bea3a42020-08-13 14:44:25 +0800216
217 status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override {
218 Parcel data, reply;
219 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
220 status_t status = remote()->transact(GET_DUAL_MONO_MODE, data, &reply);
221 if (status != NO_ERROR) {
222 return status;
223 }
224 status = (status_t)reply.readInt32();
225 if (status != NO_ERROR) {
226 return status;
227 }
228 *mode = (audio_dual_mono_mode_t)reply.readInt32();
229 return NO_ERROR;
230 }
231
232 status_t setDualMonoMode(audio_dual_mono_mode_t mode) override {
233 Parcel data, reply;
234 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
235 data.writeInt32((int32_t)mode);
236 status_t status = remote()->transact(SET_DUAL_MONO_MODE, data, &reply);
237 if (status != NO_ERROR) {
238 return status;
239 }
240 return reply.readInt32();
241 }
242
243 status_t getAudioDescriptionMixLevel(float* leveldB) override {
244 Parcel data, reply;
245 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
246 status_t status = remote()->transact(GET_AUDIO_DESCRIPTION_MIX_LEVEL, data, &reply);
247 if (status != NO_ERROR) {
248 return status;
249 }
250 status = (status_t)reply.readInt32();
251 if (status != NO_ERROR) {
252 return status;
253 }
254 *leveldB = reply.readFloat();
255 return NO_ERROR;
256 }
257
258 status_t setAudioDescriptionMixLevel(float leveldB) override {
259 Parcel data, reply;
260 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
261 data.writeFloat(leveldB);
262 status_t status = remote()->transact(SET_AUDIO_DESCRIPTION_MIX_LEVEL, data, &reply);
263 if (status != NO_ERROR) {
264 return status;
265 }
266 return reply.readInt32();
267 }
268
269 status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override {
270 Parcel data, reply;
271 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
272 status_t status = remote()->transact(GET_PLAYBACK_RATE_PARAMETERS, data, &reply);
273 if (status != NO_ERROR) {
274 return status;
275 }
276 status = (status_t)reply.readInt32();
277 if (status != NO_ERROR) {
278 return status;
279 }
280 playbackRate->mSpeed = reply.readFloat();
281 playbackRate->mPitch = reply.readFloat();
282 playbackRate->mStretchMode =
283 static_cast<audio_timestretch_stretch_mode_t>(reply.readInt32());
284 playbackRate->mFallbackMode =
285 static_cast<audio_timestretch_fallback_mode_t>(reply.readInt32());
286 return NO_ERROR;
287 }
288
289 status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) override {
290 Parcel data, reply;
291 data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
292 data.writeFloat(playbackRate.mSpeed);
293 data.writeFloat(playbackRate.mPitch);
294 data.writeInt32(playbackRate.mStretchMode);
295 data.writeInt32(playbackRate.mFallbackMode);
296 status_t status = remote()->transact(SET_PLAYBACK_RATE_PARAMETERS, data, &reply);
297 if (status != NO_ERROR) {
298 return status;
299 }
300 return reply.readInt32();
301 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800302};
303
304IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
305
306// ----------------------------------------------------------------------
307
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800308status_t BnAudioTrack::onTransact(
309 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
310{
Glenn Kastene53b9ea2012-03-12 16:29:55 -0700311 switch (code) {
312 case GET_CBLK: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800313 CHECK_INTERFACE(IAudioTrack, data, reply);
Marco Nelissen06b46062014-11-14 07:58:25 -0800314 reply->writeStrongBinder(IInterface::asBinder(getCblk()));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800315 return NO_ERROR;
316 } break;
317 case START: {
318 CHECK_INTERFACE(IAudioTrack, data, reply);
Glenn Kasten3acbd052012-02-28 10:39:56 -0800319 reply->writeInt32(start());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800320 return NO_ERROR;
321 } break;
322 case STOP: {
323 CHECK_INTERFACE(IAudioTrack, data, reply);
324 stop();
325 return NO_ERROR;
326 } break;
327 case FLUSH: {
328 CHECK_INTERFACE(IAudioTrack, data, reply);
329 flush();
330 return NO_ERROR;
331 } break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800332 case PAUSE: {
333 CHECK_INTERFACE(IAudioTrack, data, reply);
334 pause();
335 return NO_ERROR;
336 }
Eric Laurentbe916aa2010-06-01 23:49:17 -0700337 case ATTACH_AUX_EFFECT: {
338 CHECK_INTERFACE(IAudioTrack, data, reply);
339 reply->writeInt32(attachAuxEffect(data.readInt32()));
340 return NO_ERROR;
341 } break;
Richard Fitzgeraldad3af332013-03-25 16:54:37 +0000342 case SET_PARAMETERS: {
343 CHECK_INTERFACE(IAudioTrack, data, reply);
344 String8 keyValuePairs(data.readString8());
345 reply->writeInt32(setParameters(keyValuePairs));
346 return NO_ERROR;
347 } break;
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800348 case SELECT_PRESENTATION: {
349 CHECK_INTERFACE(IAudioTrack, data, reply);
350 reply->writeInt32(selectPresentation(data.readInt32(), data.readInt32()));
351 return NO_ERROR;
352 } break;
Glenn Kasten53cec222013-08-29 09:01:02 -0700353 case GET_TIMESTAMP: {
354 CHECK_INTERFACE(IAudioTrack, data, reply);
355 AudioTimestamp timestamp;
356 status_t status = getTimestamp(timestamp);
357 reply->writeInt32(status);
358 if (status == NO_ERROR) {
359 reply->writeInt32(timestamp.mPosition);
360 reply->writeInt32(timestamp.mTime.tv_sec);
361 reply->writeInt32(timestamp.mTime.tv_nsec);
362 }
363 return NO_ERROR;
364 } break;
Eric Laurent59fe0102013-09-27 18:48:26 -0700365 case SIGNAL: {
366 CHECK_INTERFACE(IAudioTrack, data, reply);
367 signal();
368 return NO_ERROR;
369 } break;
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800370 case APPLY_VOLUME_SHAPER: {
371 CHECK_INTERFACE(IAudioTrack, data, reply);
372 sp<VolumeShaper::Configuration> configuration;
373 sp<VolumeShaper::Operation> operation;
374
375 int32_t present;
376 status_t status = data.readInt32(&present);
377 if (status == NO_ERROR && present != 0) {
378 configuration = new VolumeShaper::Configuration();
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700379 status = configuration->readFromParcel(&data);
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800380 }
381 status = status ?: data.readInt32(&present);
382 if (status == NO_ERROR && present != 0) {
383 operation = new VolumeShaper::Operation();
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700384 status = operation->readFromParcel(&data);
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800385 }
386 if (status == NO_ERROR) {
387 status = (status_t)applyVolumeShaper(configuration, operation);
388 }
389 reply->writeInt32(status);
390 return NO_ERROR;
391 } break;
392 case GET_VOLUME_SHAPER_STATE: {
393 CHECK_INTERFACE(IAudioTrack, data, reply);
394 int id;
395 status_t status = data.readInt32(&id);
396 if (status == NO_ERROR) {
397 sp<VolumeShaper::State> state = getVolumeShaperState(id);
398 if (state.get() != nullptr) {
399 status = state->writeToParcel(reply);
400 }
401 }
402 return NO_ERROR;
403 } break;
Kuowei Li3bea3a42020-08-13 14:44:25 +0800404 case SET_DUAL_MONO_MODE: {
405 CHECK_INTERFACE(IAudioTrack, data, reply);
406 reply->writeInt32( setDualMonoMode((audio_dual_mono_mode_t)data.readInt32()) );
407 return NO_ERROR;
408 } break;
409 case GET_DUAL_MONO_MODE: {
410 CHECK_INTERFACE(IAudioTrack, data, reply);
411 audio_dual_mono_mode_t mode;
412 const status_t status = getDualMonoMode(&mode);
413 reply->writeInt32((int32_t)status);
414 if (status == NO_ERROR) {
415 reply->writeInt32(mode);
416 }
417 return NO_ERROR;
418 } break;
419 case SET_AUDIO_DESCRIPTION_MIX_LEVEL: {
420 CHECK_INTERFACE(IAudioTrack, data, reply);
421 reply->writeInt32( setAudioDescriptionMixLevel(data.readFloat()) );
422 return NO_ERROR;
423 } break;
424 case GET_AUDIO_DESCRIPTION_MIX_LEVEL: {
425 CHECK_INTERFACE(IAudioTrack, data, reply);
426 float f;
427 const status_t status = getAudioDescriptionMixLevel(&f);
428 reply->writeInt32((int32_t)status);
429 if (status == NO_ERROR) {
430 reply->writeFloat(f);
431 }
432 return NO_ERROR;
433 } break;
434 case SET_PLAYBACK_RATE_PARAMETERS: {
435 CHECK_INTERFACE(IAudioTrack, data, reply);
436 audio_playback_rate_t playbackRate = {
437 data.readFloat(),
438 data.readFloat(),
439 static_cast<audio_timestretch_stretch_mode_t>(data.readInt32()),
440 static_cast<audio_timestretch_fallback_mode_t>(data.readInt32())};
441 reply->writeInt32( setPlaybackRateParameters(playbackRate) );
442 return NO_ERROR;
443 } break;
444 case GET_PLAYBACK_RATE_PARAMETERS: {
445 CHECK_INTERFACE(IAudioTrack, data, reply);
446 audio_playback_rate_t playbackRate;
447 const status_t status = getPlaybackRateParameters(&playbackRate);
448 reply->writeInt32((int32_t)status);
449 if (status == NO_ERROR) {
450 reply->writeFloat(playbackRate.mSpeed);
451 reply->writeFloat(playbackRate.mPitch);
452 reply->writeInt32(playbackRate.mStretchMode);
453 reply->writeInt32(playbackRate.mFallbackMode);
454 }
455 return NO_ERROR;
456 } break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800457 default:
458 return BBinder::onTransact(code, data, reply, flags);
459 }
460}
461
Glenn Kasten40bc9062015-03-20 09:09:33 -0700462} // namespace android