blob: 87bb01428a7a26c518b1fdec5ab9f659343262d9 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/servers/AudioFlinger/AudioDumpInterface.cpp
2**
3** Copyright 2008, 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 "AudioFlingerDump"
Eric Laurenta553c252009-07-17 12:17:14 -070019//#define LOG_NDEBUG 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020
21#include <stdint.h>
22#include <sys/types.h>
23#include <utils/Log.h>
24
25#include <stdlib.h>
26#include <unistd.h>
27
28#include "AudioDumpInterface.h"
29
30namespace android {
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032// ----------------------------------------------------------------------------
33
34AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw)
Eric Laurenta553c252009-07-17 12:17:14 -070035 : mFirstHwOutput(true), mPolicyCommands(String8("")), mFileName(String8(""))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036{
37 if(hw == 0) {
38 LOGE("Dump construct hw = 0");
39 }
40 mFinalInterface = hw;
Eric Laurenta553c252009-07-17 12:17:14 -070041 LOGV("Constructor %p, mFinalInterface %p", this, mFinalInterface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042}
43
44
45AudioDumpInterface::~AudioDumpInterface()
46{
Eric Laurenta553c252009-07-17 12:17:14 -070047 for (size_t i = 0; i < mOutputs.size(); i++) {
48 closeOutputStream((AudioStreamOut *)mOutputs[i]);
49 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 if(mFinalInterface) delete mFinalInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051}
52
53
54AudioStreamOut* AudioDumpInterface::openOutputStream(
Eric Laurenta553c252009-07-17 12:17:14 -070055 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056{
Eric Laurenta553c252009-07-17 12:17:14 -070057 AudioStreamOut* outFinal = NULL;
58 int lFormat = AudioSystem::PCM_16_BIT;
59 uint32_t lChannels = AudioSystem::CHANNEL_OUT_STEREO;
60 uint32_t lRate = 44100;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061
Eric Laurenta553c252009-07-17 12:17:14 -070062
63 if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices) || mFirstHwOutput) {
64 outFinal = mFinalInterface->openOutputStream(devices, format, channels, sampleRate, status);
65 if (outFinal != 0) {
66 lFormat = outFinal->format();
67 lChannels = outFinal->channels();
68 lRate = outFinal->sampleRate();
69 if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
70 mFirstHwOutput = false;
71 }
72 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 } else {
Eric Laurenta553c252009-07-17 12:17:14 -070074 if (format != 0 && *format != 0) lFormat = *format;
75 if (channels != 0 && *channels != 0) lChannels = *channels;
76 if (sampleRate != 0 && *sampleRate != 0) lRate = *sampleRate;
77 if (status) *status = NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078 }
Eric Laurenta553c252009-07-17 12:17:14 -070079 LOGV("openOutputStream(), outFinal %p", outFinal);
80
81 AudioStreamOutDump *dumOutput = new AudioStreamOutDump(this, mOutputs.size(), outFinal,
82 devices, lFormat, lChannels, lRate);
83 mOutputs.add(dumOutput);
84
85 return dumOutput;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086}
87
Eric Laurenta553c252009-07-17 12:17:14 -070088void AudioDumpInterface::closeOutputStream(AudioStreamOut* out)
89{
90 AudioStreamOutDump *dumpOut = (AudioStreamOutDump *)out;
91
92 if (mOutputs.indexOf(dumpOut) < 0) {
93 LOGW("Attempt to close invalid output stream");
94 return;
95 }
96 dumpOut->standby();
97 if (dumpOut->finalStream() != NULL) {
98 mFinalInterface->closeOutputStream(dumpOut->finalStream());
99 }
100
101 mOutputs.remove(dumpOut);
102 delete dumpOut;
103}
104
105AudioStreamIn* AudioDumpInterface::openInputStream(uint32_t devices, int *format, uint32_t *channels,
106 uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
107{
108 AudioStreamIn* inFinal = NULL;
109 int lFormat = AudioSystem::PCM_16_BIT;
110 uint32_t lChannels = AudioSystem::CHANNEL_IN_MONO;
111 uint32_t lRate = 8000;
112
113
114 if (mInputs.size() == 0) {
115 inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
116 if (inFinal == 0) return 0;
117
118 lFormat = inFinal->format();
119 lChannels = inFinal->channels();
120 lRate = inFinal->sampleRate();
121 } else {
122 if (format != 0 && *format != 0) lFormat = *format;
123 if (channels != 0 && *channels != 0) lChannels = *channels;
124 if (sampleRate != 0 && *sampleRate != 0) lRate = *sampleRate;
125 if (status) *status = NO_ERROR;
126 }
127 LOGV("openInputStream(), inFinal %p", inFinal);
128
129 AudioStreamInDump *dumInput = new AudioStreamInDump(this, mInputs.size(), inFinal,
130 devices, lFormat, lChannels, lRate);
131 mInputs.add(dumInput);
132
133 return dumInput;
134}
135void AudioDumpInterface::closeInputStream(AudioStreamIn* in)
136{
137 AudioStreamInDump *dumpIn = (AudioStreamInDump *)in;
138
139 if (mInputs.indexOf(dumpIn) < 0) {
140 LOGW("Attempt to close invalid input stream");
141 return;
142 }
143 dumpIn->standby();
144 if (dumpIn->finalStream() != NULL) {
145 mFinalInterface->closeInputStream(dumpIn->finalStream());
146 }
147
148 mInputs.remove(dumpIn);
149 delete dumpIn;
150}
151
152
153status_t AudioDumpInterface::setParameters(const String8& keyValuePairs)
154{
155 AudioParameter param = AudioParameter(keyValuePairs);
156 String8 value;
157 int valueInt;
158 LOGV("setParameters %s", keyValuePairs.string());
159
160 if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
161 mFileName = value;
162 return NO_ERROR;
163 }
164 if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
165 Mutex::Autolock _l(mLock);
166 param.remove(String8("test_cmd_policy"));
167 mPolicyCommands = param.toString();
168 LOGV("test_cmd_policy command %s written", mPolicyCommands.string());
169 return NO_ERROR;
170 }
171
172 if (mFinalInterface != 0 ) return mFinalInterface->setParameters(keyValuePairs);
173 return NO_ERROR;
174}
175
176String8 AudioDumpInterface::getParameters(const String8& keys)
177{
178 AudioParameter param = AudioParameter(keys);
179 String8 value;
180
181// LOGV("getParameters %s", keys.string());
182
183 if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
184 return mFileName;
185 }
186 if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
187 Mutex::Autolock _l(mLock);
188// LOGV("test_cmd_policy command %s read", mPolicyCommands.string());
189 return mPolicyCommands;
190 }
191
192 if (mFinalInterface != 0 ) return mFinalInterface->getParameters(keys);
193 return String8("");
194}
195
196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197// ----------------------------------------------------------------------------
198
Eric Laurenta553c252009-07-17 12:17:14 -0700199AudioStreamOutDump::AudioStreamOutDump(AudioDumpInterface *interface,
200 int id,
201 AudioStreamOut* finalStream,
202 uint32_t devices,
203 int format,
204 uint32_t channels,
205 uint32_t sampleRate)
206 : mInterface(interface), mId(id),
207 mSampleRate(sampleRate), mFormat(format), mChannels(channels), mLatency(0), mDevice(devices),
208 mBufferSize(1024), mFinalStream(finalStream), mOutFile(0), mFileCount(0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209{
Eric Laurenta553c252009-07-17 12:17:14 -0700210 LOGV("AudioStreamOutDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211}
212
213
214AudioStreamOutDump::~AudioStreamOutDump()
215{
216 Close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217}
218
219ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes)
220{
221 ssize_t ret;
222
Eric Laurenta553c252009-07-17 12:17:14 -0700223 if (mFinalStream) {
224 ret = mFinalStream->write(buffer, bytes);
225 } else {
226 usleep((bytes * 1000000) / frameSize() / sampleRate());
227 ret = bytes;
228 }
229 if(!mOutFile) {
230 if (mInterface->fileName() != "") {
231 char name[255];
232 sprintf(name, "%s_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
233 mOutFile = fopen(name, "wb");
234 LOGV("Opening dump file %s, fh %p", name, mOutFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 }
236 }
237 if (mOutFile) {
238 fwrite(buffer, bytes, 1, mOutFile);
239 }
240 return ret;
241}
242
243status_t AudioStreamOutDump::standby()
244{
Eric Laurenta553c252009-07-17 12:17:14 -0700245 LOGV("AudioStreamOutDump standby(), mOutFile %p, mFinalStream %p", mOutFile, mFinalStream);
246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 Close();
Eric Laurenta553c252009-07-17 12:17:14 -0700248 if (mFinalStream != 0 ) return mFinalStream->standby();
249 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250}
251
Eric Laurenta553c252009-07-17 12:17:14 -0700252uint32_t AudioStreamOutDump::sampleRate() const
253{
254 if (mFinalStream != 0 ) return mFinalStream->sampleRate();
255 return mSampleRate;
256}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257
Eric Laurenta553c252009-07-17 12:17:14 -0700258size_t AudioStreamOutDump::bufferSize() const
259{
260 if (mFinalStream != 0 ) return mFinalStream->bufferSize();
261 return mBufferSize;
262}
263
264uint32_t AudioStreamOutDump::channels() const
265{
266 if (mFinalStream != 0 ) return mFinalStream->channels();
267 return mChannels;
268}
269int AudioStreamOutDump::format() const
270{
271 if (mFinalStream != 0 ) return mFinalStream->format();
272 return mFormat;
273}
274uint32_t AudioStreamOutDump::latency() const
275{
276 if (mFinalStream != 0 ) return mFinalStream->latency();
277 return 0;
278}
279status_t AudioStreamOutDump::setVolume(float left, float right)
280{
281 if (mFinalStream != 0 ) return mFinalStream->setVolume(left, right);
282 return NO_ERROR;
283}
284status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs)
285{
286 LOGV("AudioStreamOutDump::setParameters()");
287 if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
288 return NO_ERROR;
289}
290String8 AudioStreamOutDump::getParameters(const String8& keys)
291{
292 String8 result = String8("");
293 if (mFinalStream != 0 ) result = mFinalStream->getParameters(keys);
294 return result;
295}
296
297status_t AudioStreamOutDump::dump(int fd, const Vector<String16>& args)
298{
299 if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
300 return NO_ERROR;
301}
302
303void AudioStreamOutDump::Close()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304{
305 if(mOutFile) {
306 fclose(mOutFile);
307 mOutFile = 0;
308 }
309}
310
Eric Laurenta553c252009-07-17 12:17:14 -0700311// ----------------------------------------------------------------------------
312
313AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
314 int id,
315 AudioStreamIn* finalStream,
316 uint32_t devices,
317 int format,
318 uint32_t channels,
319 uint32_t sampleRate)
320 : mInterface(interface), mId(id),
321 mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices),
322 mBufferSize(1024), mFinalStream(finalStream), mInFile(0)
323{
324 LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
325}
326
327
328AudioStreamInDump::~AudioStreamInDump()
329{
330 Close();
331}
332
333ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes)
334{
335 if (mFinalStream) {
336 return mFinalStream->read(buffer, bytes);
337 }
338
339 usleep((bytes * 1000000) / frameSize() / sampleRate());
340
341 if(!mInFile) {
342 char name[255];
343 strcpy(name, "/sdcard/music/sine440");
344 if (channels() == AudioSystem::CHANNEL_IN_MONO) {
345 strcat(name, "_mo");
346 } else {
347 strcat(name, "_st");
348 }
349 if (format() == AudioSystem::PCM_16_BIT) {
350 strcat(name, "_16b");
351 } else {
352 strcat(name, "_8b");
353 }
354 if (sampleRate() < 16000) {
355 strcat(name, "_8k");
356 } else if (sampleRate() < 32000) {
357 strcat(name, "_22k");
358 } else if (sampleRate() < 48000) {
359 strcat(name, "_44k");
360 } else {
361 strcat(name, "_48k");
362 }
363 strcat(name, ".wav");
364 mInFile = fopen(name, "rb");
365 LOGV("Opening dump file %s, fh %p", name, mInFile);
366 if (mInFile) {
367 fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
368 }
369
370 }
371 if (mInFile) {
372 ssize_t bytesRead = fread(buffer, bytes, 1, mInFile);
373 if (bytesRead != bytes) {
374 fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
375 fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mInFile);
376 }
377 }
378 return bytes;
379}
380
381status_t AudioStreamInDump::standby()
382{
383 LOGV("AudioStreamInDump standby(), mInFile %p, mFinalStream %p", mInFile, mFinalStream);
384
385 Close();
386 if (mFinalStream != 0 ) return mFinalStream->standby();
387 return NO_ERROR;
388}
389
390status_t AudioStreamInDump::setGain(float gain)
391{
392 if (mFinalStream != 0 ) return mFinalStream->setGain(gain);
393 return NO_ERROR;
394}
395
396uint32_t AudioStreamInDump::sampleRate() const
397{
398 if (mFinalStream != 0 ) return mFinalStream->sampleRate();
399 return mSampleRate;
400}
401
402size_t AudioStreamInDump::bufferSize() const
403{
404 if (mFinalStream != 0 ) return mFinalStream->bufferSize();
405 return mBufferSize;
406}
407
408uint32_t AudioStreamInDump::channels() const
409{
410 if (mFinalStream != 0 ) return mFinalStream->channels();
411 return mChannels;
412}
413
414int AudioStreamInDump::format() const
415{
416 if (mFinalStream != 0 ) return mFinalStream->format();
417 return mFormat;
418}
419
420status_t AudioStreamInDump::setParameters(const String8& keyValuePairs)
421{
422 LOGV("AudioStreamInDump::setParameters()");
423 if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
424 return NO_ERROR;
425}
426
427String8 AudioStreamInDump::getParameters(const String8& keys)
428{
429 String8 result = String8("");
430 if (mFinalStream != 0 ) result = mFinalStream->getParameters(keys);
431 return result;
432}
433
434status_t AudioStreamInDump::dump(int fd, const Vector<String16>& args)
435{
436 if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
437 return NO_ERROR;
438}
439
440void AudioStreamInDump::Close()
441{
442 if(mInFile) {
443 fclose(mInFile);
444 mInFile = 0;
445 }
446}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447}; // namespace android