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