Home | History | Annotate | Download | only in audioflinger
      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     : 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 
     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 
     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 
    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 
    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 }
    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 
    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 
    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 
    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 
    244 AudioStreamOutDump::~AudioStreamOutDump()
    245 {
    246     LOGV("AudioStreamOutDump destructor");
    247     Close();
    248 }
    249 
    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 
    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 
    283 uint32_t AudioStreamOutDump::sampleRate() const
    284 {
    285     if (mFinalStream != 0 ) return mFinalStream->sampleRate();
    286     return mSampleRate;
    287 }
    288 
    289 size_t AudioStreamOutDump::bufferSize() const
    290 {
    291     if (mFinalStream != 0 ) return mFinalStream->bufferSize();
    292     return mBufferSize;
    293 }
    294 
    295 uint32_t AudioStreamOutDump::channels() const
    296 {
    297     if (mFinalStream != 0 ) return mFinalStream->channels();
    298     return mChannels;
    299 }
    300 int AudioStreamOutDump::format() const
    301 {
    302     if (mFinalStream != 0 ) return mFinalStream->format();
    303     return mFormat;
    304 }
    305 uint32_t AudioStreamOutDump::latency() const
    306 {
    307     if (mFinalStream != 0 ) return mFinalStream->latency();
    308     return 0;
    309 }
    310 status_t AudioStreamOutDump::setVolume(float left, float right)
    311 {
    312     if (mFinalStream != 0 ) return mFinalStream->setVolume(left, right);
    313     return NO_ERROR;
    314 }
    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 
    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 
    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 
    374 void AudioStreamOutDump::Close()
    375 {
    376     if(mOutFile) {
    377         fclose(mOutFile);
    378         mOutFile = 0;
    379     }
    380 }
    381 
    382 status_t AudioStreamOutDump::getRenderPosition(uint32_t *dspFrames)
    383 {
    384     if (mFinalStream != 0 ) return mFinalStream->getRenderPosition(dspFrames);
    385     return INVALID_OPERATION;
    386 }
    387 
    388 // ----------------------------------------------------------------------------
    389 
    390 AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
    391                                         int id,
    392                                         AudioStreamIn* finalStream,
    393                                         uint32_t devices,
    394                                         int format,
    395                                         uint32_t channels,
    396                                         uint32_t sampleRate)
    397     : mInterface(interface), mId(id),
    398       mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices),
    399       mBufferSize(1024), mFinalStream(finalStream), mInFile(0)
    400 {
    401     LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
    402 }
    403 
    404 
    405 AudioStreamInDump::~AudioStreamInDump()
    406 {
    407     Close();
    408 }
    409 
    410 ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes)
    411 {
    412     if (mFinalStream) {
    413         return mFinalStream->read(buffer, bytes);
    414     }
    415 
    416     usleep((bytes * 1000000) / frameSize() / sampleRate());
    417 
    418     if(!mInFile) {
    419         char name[255];
    420         strcpy(name, "/sdcard/music/sine440");
    421         if (channels() == AudioSystem::CHANNEL_IN_MONO) {
    422             strcat(name, "_mo");
    423         } else {
    424             strcat(name, "_st");
    425         }
    426         if (format() == AudioSystem::PCM_16_BIT) {
    427             strcat(name, "_16b");
    428         } else {
    429             strcat(name, "_8b");
    430         }
    431         if (sampleRate() < 16000) {
    432             strcat(name, "_8k");
    433         } else if (sampleRate() < 32000) {
    434             strcat(name, "_22k");
    435         } else if (sampleRate() < 48000) {
    436             strcat(name, "_44k");
    437         } else {
    438             strcat(name, "_48k");
    439         }
    440         strcat(name, ".wav");
    441         mInFile = fopen(name, "rb");
    442         LOGV("Opening dump file %s, fh %p", name, mInFile);
    443         if (mInFile) {
    444             fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
    445         }
    446 
    447     }
    448     if (mInFile) {
    449         ssize_t bytesRead = fread(buffer, bytes, 1, mInFile);
    450         if (bytesRead != bytes) {
    451             fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
    452             fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mInFile);
    453         }
    454     }
    455     return bytes;
    456 }
    457 
    458 status_t AudioStreamInDump::standby()
    459 {
    460     LOGV("AudioStreamInDump standby(), mInFile %p, mFinalStream %p", mInFile, mFinalStream);
    461 
    462     Close();
    463     if (mFinalStream != 0 ) return mFinalStream->standby();
    464     return NO_ERROR;
    465 }
    466 
    467 status_t AudioStreamInDump::setGain(float gain)
    468 {
    469     if (mFinalStream != 0 ) return mFinalStream->setGain(gain);
    470     return NO_ERROR;
    471 }
    472 
    473 uint32_t AudioStreamInDump::sampleRate() const
    474 {
    475     if (mFinalStream != 0 ) return mFinalStream->sampleRate();
    476     return mSampleRate;
    477 }
    478 
    479 size_t AudioStreamInDump::bufferSize() const
    480 {
    481     if (mFinalStream != 0 ) return mFinalStream->bufferSize();
    482     return mBufferSize;
    483 }
    484 
    485 uint32_t AudioStreamInDump::channels() const
    486 {
    487     if (mFinalStream != 0 ) return mFinalStream->channels();
    488     return mChannels;
    489 }
    490 
    491 int AudioStreamInDump::format() const
    492 {
    493     if (mFinalStream != 0 ) return mFinalStream->format();
    494     return mFormat;
    495 }
    496 
    497 status_t AudioStreamInDump::setParameters(const String8& keyValuePairs)
    498 {
    499     LOGV("AudioStreamInDump::setParameters()");
    500     if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
    501     return NO_ERROR;
    502 }
    503 
    504 String8 AudioStreamInDump::getParameters(const String8& keys)
    505 {
    506     if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
    507 
    508     AudioParameter param = AudioParameter(keys);
    509     return param.toString();
    510 }
    511 
    512 unsigned int AudioStreamInDump::getInputFramesLost() const
    513 {
    514     if (mFinalStream != 0 ) return mFinalStream->getInputFramesLost();
    515     return 0;
    516 }
    517 
    518 status_t AudioStreamInDump::dump(int fd, const Vector<String16>& args)
    519 {
    520     if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
    521     return NO_ERROR;
    522 }
    523 
    524 void AudioStreamInDump::Close()
    525 {
    526     if(mInFile) {
    527         fclose(mInFile);
    528         mInFile = 0;
    529     }
    530 }
    531 }; // namespace android
    532