• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* //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"
19 //#define LOG_NDEBUG 0
20 
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 
30 namespace android {
31 
32 // ----------------------------------------------------------------------------
33 
AudioDumpInterface(AudioHardwareInterface * hw)34 AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw)
35     : mFirstHwOutput(true), mPolicyCommands(String8("")), mFileName(String8(""))
36 {
37     if(hw == 0) {
38         LOGE("Dump construct hw = 0");
39     }
40     mFinalInterface = hw;
41     LOGV("Constructor %p, mFinalInterface %p", this, mFinalInterface);
42 }
43 
44 
~AudioDumpInterface()45 AudioDumpInterface::~AudioDumpInterface()
46 {
47     for (size_t i = 0; i < mOutputs.size(); i++) {
48         closeOutputStream((AudioStreamOut *)mOutputs[i]);
49     }
50     if(mFinalInterface) delete mFinalInterface;
51 }
52 
53 
openOutputStream(uint32_t devices,int * format,uint32_t * channels,uint32_t * sampleRate,status_t * status)54 AudioStreamOut* AudioDumpInterface::openOutputStream(
55         uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
56 {
57     AudioStreamOut* outFinal = NULL;
58     int lFormat = AudioSystem::PCM_16_BIT;
59     uint32_t lChannels = AudioSystem::CHANNEL_OUT_STEREO;
60     uint32_t lRate = 44100;
61 
62 
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         }
73     } else {
74         if (format != 0 && *format != 0) {
75             lFormat = *format;
76         } else {
77             lFormat = AudioSystem::PCM_16_BIT;
78         }
79         if (channels != 0 && *channels != 0) {
80             lChannels = *channels;
81         } else {
82             lChannels = AudioSystem::CHANNEL_OUT_STEREO;
83         }
84         if (sampleRate != 0 && *sampleRate != 0) {
85             lRate = *sampleRate;
86         } else {
87             lRate = 44100;
88         }
89         if (status) *status = NO_ERROR;
90     }
91     LOGV("openOutputStream(), outFinal %p", outFinal);
92 
93     AudioStreamOutDump *dumOutput = new AudioStreamOutDump(this, mOutputs.size(), outFinal,
94             devices, lFormat, lChannels, lRate);
95     mOutputs.add(dumOutput);
96 
97     return dumOutput;
98 }
99 
closeOutputStream(AudioStreamOut * out)100 void AudioDumpInterface::closeOutputStream(AudioStreamOut* out)
101 {
102     AudioStreamOutDump *dumpOut = (AudioStreamOutDump *)out;
103 
104     if (mOutputs.indexOf(dumpOut) < 0) {
105         LOGW("Attempt to close invalid output stream");
106         return;
107     }
108 
109     LOGV("closeOutputStream() output %p", out);
110 
111     dumpOut->standby();
112     if (dumpOut->finalStream() != NULL) {
113         mFinalInterface->closeOutputStream(dumpOut->finalStream());
114         mFirstHwOutput = true;
115     }
116 
117     mOutputs.remove(dumpOut);
118     delete dumpOut;
119 }
120 
openInputStream(uint32_t devices,int * format,uint32_t * channels,uint32_t * sampleRate,status_t * status,AudioSystem::audio_in_acoustics acoustics)121 AudioStreamIn* AudioDumpInterface::openInputStream(uint32_t devices, int *format, uint32_t *channels,
122         uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
123 {
124     AudioStreamIn* inFinal = NULL;
125     int lFormat = AudioSystem::PCM_16_BIT;
126     uint32_t lChannels = AudioSystem::CHANNEL_IN_MONO;
127     uint32_t lRate = 8000;
128 
129 
130     if (mInputs.size() == 0) {
131         inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
132         if (inFinal == 0) return 0;
133 
134         lFormat = inFinal->format();
135         lChannels = inFinal->channels();
136         lRate = inFinal->sampleRate();
137     } else {
138         if (format != 0 && *format != 0) lFormat = *format;
139         if (channels != 0 && *channels != 0) lChannels = *channels;
140         if (sampleRate != 0 && *sampleRate != 0) lRate = *sampleRate;
141         if (status) *status = NO_ERROR;
142     }
143     LOGV("openInputStream(), inFinal %p", inFinal);
144 
145     AudioStreamInDump *dumInput = new AudioStreamInDump(this, mInputs.size(), inFinal,
146             devices, lFormat, lChannels, lRate);
147     mInputs.add(dumInput);
148 
149     return dumInput;
150 }
closeInputStream(AudioStreamIn * in)151 void AudioDumpInterface::closeInputStream(AudioStreamIn* in)
152 {
153     AudioStreamInDump *dumpIn = (AudioStreamInDump *)in;
154 
155     if (mInputs.indexOf(dumpIn) < 0) {
156         LOGW("Attempt to close invalid input stream");
157         return;
158     }
159     dumpIn->standby();
160     if (dumpIn->finalStream() != NULL) {
161         mFinalInterface->closeInputStream(dumpIn->finalStream());
162     }
163 
164     mInputs.remove(dumpIn);
165     delete dumpIn;
166 }
167 
168 
setParameters(const String8 & keyValuePairs)169 status_t AudioDumpInterface::setParameters(const String8& keyValuePairs)
170 {
171     AudioParameter param = AudioParameter(keyValuePairs);
172     String8 value;
173     int valueInt;
174     LOGV("setParameters %s", keyValuePairs.string());
175 
176     if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
177         mFileName = value;
178         param.remove(String8("test_cmd_file_name"));
179     }
180     if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
181         Mutex::Autolock _l(mLock);
182         param.remove(String8("test_cmd_policy"));
183         mPolicyCommands = param.toString();
184         LOGV("test_cmd_policy command %s written", mPolicyCommands.string());
185         return NO_ERROR;
186     }
187 
188     if (mFinalInterface != 0 ) return mFinalInterface->setParameters(keyValuePairs);
189     return NO_ERROR;
190 }
191 
getParameters(const String8 & keys)192 String8 AudioDumpInterface::getParameters(const String8& keys)
193 {
194     AudioParameter param = AudioParameter(keys);
195     AudioParameter response;
196     String8 value;
197 
198 //    LOGV("getParameters %s", keys.string());
199     if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
200         Mutex::Autolock _l(mLock);
201         if (mPolicyCommands.length() != 0) {
202             response = AudioParameter(mPolicyCommands);
203             response.addInt(String8("test_cmd_policy"), 1);
204         } else {
205             response.addInt(String8("test_cmd_policy"), 0);
206         }
207         param.remove(String8("test_cmd_policy"));
208 //        LOGV("test_cmd_policy command %s read", mPolicyCommands.string());
209     }
210 
211     if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
212         response.add(String8("test_cmd_file_name"), mFileName);
213         param.remove(String8("test_cmd_file_name"));
214     }
215 
216     String8 keyValuePairs = response.toString();
217 
218     if (param.size() && mFinalInterface != 0 ) {
219         keyValuePairs += ";";
220         keyValuePairs += mFinalInterface->getParameters(param.toString());
221     }
222 
223     return keyValuePairs;
224 }
225 
226 
227 // ----------------------------------------------------------------------------
228 
AudioStreamOutDump(AudioDumpInterface * interface,int id,AudioStreamOut * finalStream,uint32_t devices,int format,uint32_t channels,uint32_t sampleRate)229 AudioStreamOutDump::AudioStreamOutDump(AudioDumpInterface *interface,
230                                         int id,
231                                         AudioStreamOut* finalStream,
232                                         uint32_t devices,
233                                         int format,
234                                         uint32_t channels,
235                                         uint32_t sampleRate)
236     : mInterface(interface), mId(id),
237       mSampleRate(sampleRate), mFormat(format), mChannels(channels), mLatency(0), mDevice(devices),
238       mBufferSize(1024), mFinalStream(finalStream), mOutFile(0), mFileCount(0)
239 {
240     LOGV("AudioStreamOutDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
241 }
242 
243 
~AudioStreamOutDump()244 AudioStreamOutDump::~AudioStreamOutDump()
245 {
246     LOGV("AudioStreamOutDump destructor");
247     Close();
248 }
249 
write(const void * buffer,size_t bytes)250 ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes)
251 {
252     ssize_t ret;
253 
254     if (mFinalStream) {
255         ret = mFinalStream->write(buffer, bytes);
256     } else {
257         usleep((bytes * 1000000) / frameSize() / sampleRate());
258         ret = bytes;
259     }
260     if(!mOutFile) {
261         if (mInterface->fileName() != "") {
262             char name[255];
263             sprintf(name, "%s_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
264             mOutFile = fopen(name, "wb");
265             LOGV("Opening dump file %s, fh %p", name, mOutFile);
266         }
267     }
268     if (mOutFile) {
269         fwrite(buffer, bytes, 1, mOutFile);
270     }
271     return ret;
272 }
273 
standby()274 status_t AudioStreamOutDump::standby()
275 {
276     LOGV("AudioStreamOutDump standby(), mOutFile %p, mFinalStream %p", mOutFile, mFinalStream);
277 
278     Close();
279     if (mFinalStream != 0 ) return mFinalStream->standby();
280     return NO_ERROR;
281 }
282 
sampleRate() const283 uint32_t AudioStreamOutDump::sampleRate() const
284 {
285     if (mFinalStream != 0 ) return mFinalStream->sampleRate();
286     return mSampleRate;
287 }
288 
bufferSize() const289 size_t AudioStreamOutDump::bufferSize() const
290 {
291     if (mFinalStream != 0 ) return mFinalStream->bufferSize();
292     return mBufferSize;
293 }
294 
channels() const295 uint32_t AudioStreamOutDump::channels() const
296 {
297     if (mFinalStream != 0 ) return mFinalStream->channels();
298     return mChannels;
299 }
format() const300 int AudioStreamOutDump::format() const
301 {
302     if (mFinalStream != 0 ) return mFinalStream->format();
303     return mFormat;
304 }
latency() const305 uint32_t AudioStreamOutDump::latency() const
306 {
307     if (mFinalStream != 0 ) return mFinalStream->latency();
308     return 0;
309 }
setVolume(float left,float right)310 status_t AudioStreamOutDump::setVolume(float left, float right)
311 {
312     if (mFinalStream != 0 ) return mFinalStream->setVolume(left, right);
313     return NO_ERROR;
314 }
setParameters(const String8 & keyValuePairs)315 status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs)
316 {
317     LOGV("AudioStreamOutDump::setParameters %s", keyValuePairs.string());
318 
319     if (mFinalStream != 0 ) {
320         return mFinalStream->setParameters(keyValuePairs);
321     }
322 
323     AudioParameter param = AudioParameter(keyValuePairs);
324     String8 value;
325     int valueInt;
326     status_t status = NO_ERROR;
327 
328     if (param.getInt(String8("set_id"), valueInt) == NO_ERROR) {
329         mId = valueInt;
330     }
331 
332     if (param.getInt(String8("format"), valueInt) == NO_ERROR) {
333         if (mOutFile == 0) {
334             mFormat = valueInt;
335         } else {
336             status = INVALID_OPERATION;
337         }
338     }
339     if (param.getInt(String8("channels"), valueInt) == NO_ERROR) {
340         if (valueInt == AudioSystem::CHANNEL_OUT_STEREO || valueInt == AudioSystem::CHANNEL_OUT_MONO) {
341             mChannels = valueInt;
342         } else {
343             status = BAD_VALUE;
344         }
345     }
346     if (param.getInt(String8("sampling_rate"), valueInt) == NO_ERROR) {
347         if (valueInt > 0 && valueInt <= 48000) {
348             if (mOutFile == 0) {
349                 mSampleRate = valueInt;
350             } else {
351                 status = INVALID_OPERATION;
352             }
353         } else {
354             status = BAD_VALUE;
355         }
356     }
357     return status;
358 }
359 
getParameters(const String8 & keys)360 String8 AudioStreamOutDump::getParameters(const String8& keys)
361 {
362     if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
363 
364     AudioParameter param = AudioParameter(keys);
365     return param.toString();
366 }
367 
dump(int fd,const Vector<String16> & args)368 status_t AudioStreamOutDump::dump(int fd, const Vector<String16>& args)
369 {
370     if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
371     return NO_ERROR;
372 }
373 
Close()374 void AudioStreamOutDump::Close()
375 {
376     if(mOutFile) {
377         fclose(mOutFile);
378         mOutFile = 0;
379     }
380 }
381 
382 // ----------------------------------------------------------------------------
383 
AudioStreamInDump(AudioDumpInterface * interface,int id,AudioStreamIn * finalStream,uint32_t devices,int format,uint32_t channels,uint32_t sampleRate)384 AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
385                                         int id,
386                                         AudioStreamIn* finalStream,
387                                         uint32_t devices,
388                                         int format,
389                                         uint32_t channels,
390                                         uint32_t sampleRate)
391     : mInterface(interface), mId(id),
392       mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices),
393       mBufferSize(1024), mFinalStream(finalStream), mInFile(0)
394 {
395     LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
396 }
397 
398 
~AudioStreamInDump()399 AudioStreamInDump::~AudioStreamInDump()
400 {
401     Close();
402 }
403 
read(void * buffer,ssize_t bytes)404 ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes)
405 {
406     if (mFinalStream) {
407         return mFinalStream->read(buffer, bytes);
408     }
409 
410     usleep((bytes * 1000000) / frameSize() / sampleRate());
411 
412     if(!mInFile) {
413         char name[255];
414         strcpy(name, "/sdcard/music/sine440");
415         if (channels() == AudioSystem::CHANNEL_IN_MONO) {
416             strcat(name, "_mo");
417         } else {
418             strcat(name, "_st");
419         }
420         if (format() == AudioSystem::PCM_16_BIT) {
421             strcat(name, "_16b");
422         } else {
423             strcat(name, "_8b");
424         }
425         if (sampleRate() < 16000) {
426             strcat(name, "_8k");
427         } else if (sampleRate() < 32000) {
428             strcat(name, "_22k");
429         } else if (sampleRate() < 48000) {
430             strcat(name, "_44k");
431         } else {
432             strcat(name, "_48k");
433         }
434         strcat(name, ".wav");
435         mInFile = fopen(name, "rb");
436         LOGV("Opening dump file %s, fh %p", name, mInFile);
437         if (mInFile) {
438             fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
439         }
440 
441     }
442     if (mInFile) {
443         ssize_t bytesRead = fread(buffer, bytes, 1, mInFile);
444         if (bytesRead != bytes) {
445             fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
446             fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mInFile);
447         }
448     }
449     return bytes;
450 }
451 
standby()452 status_t AudioStreamInDump::standby()
453 {
454     LOGV("AudioStreamInDump standby(), mInFile %p, mFinalStream %p", mInFile, mFinalStream);
455 
456     Close();
457     if (mFinalStream != 0 ) return mFinalStream->standby();
458     return NO_ERROR;
459 }
460 
setGain(float gain)461 status_t AudioStreamInDump::setGain(float gain)
462 {
463     if (mFinalStream != 0 ) return mFinalStream->setGain(gain);
464     return NO_ERROR;
465 }
466 
sampleRate() const467 uint32_t AudioStreamInDump::sampleRate() const
468 {
469     if (mFinalStream != 0 ) return mFinalStream->sampleRate();
470     return mSampleRate;
471 }
472 
bufferSize() const473 size_t AudioStreamInDump::bufferSize() const
474 {
475     if (mFinalStream != 0 ) return mFinalStream->bufferSize();
476     return mBufferSize;
477 }
478 
channels() const479 uint32_t AudioStreamInDump::channels() const
480 {
481     if (mFinalStream != 0 ) return mFinalStream->channels();
482     return mChannels;
483 }
484 
format() const485 int AudioStreamInDump::format() const
486 {
487     if (mFinalStream != 0 ) return mFinalStream->format();
488     return mFormat;
489 }
490 
setParameters(const String8 & keyValuePairs)491 status_t AudioStreamInDump::setParameters(const String8& keyValuePairs)
492 {
493     LOGV("AudioStreamInDump::setParameters()");
494     if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
495     return NO_ERROR;
496 }
497 
getParameters(const String8 & keys)498 String8 AudioStreamInDump::getParameters(const String8& keys)
499 {
500     if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
501 
502     AudioParameter param = AudioParameter(keys);
503     return param.toString();
504 }
505 
dump(int fd,const Vector<String16> & args)506 status_t AudioStreamInDump::dump(int fd, const Vector<String16>& args)
507 {
508     if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
509     return NO_ERROR;
510 }
511 
Close()512 void AudioStreamInDump::Close()
513 {
514     if(mInFile) {
515         fclose(mInFile);
516         mInFile = 0;
517     }
518 }
519 }; // namespace android
520