AudioHardware.cpp revision 3fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26
1/* 2** Copyright 2008, The Android Open-Source Project 3** 4** Licensed under the Apache License, Version 2.0 (the "License"); 5** you may not use this file except in compliance with the License. 6** You may obtain a copy of the License at 7** 8** http://www.apache.org/licenses/LICENSE-2.0 9** 10** Unless required by applicable law or agreed to in writing, software 11** distributed under the License is distributed on an "AS IS" BASIS, 12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13** See the License for the specific language governing permissions and 14** limitations under the License. 15*/ 16 17#include <math.h> 18 19//#define LOG_NDEBUG 0 20#define LOG_TAG "AudioHardware" 21 22#include <utils/Log.h> 23#include <utils/String8.h> 24//#include <hardware_legacy/power.h> 25 26#include <stdio.h> 27#include <unistd.h> 28#include <sys/ioctl.h> 29#include <sys/types.h> 30#include <sys/stat.h> 31#include <dlfcn.h> 32#include <fcntl.h> 33 34#include "AudioHardware.h" 35#include <media/AudioRecord.h> 36 37extern "C" { 38#include "msm_audio.h" 39} 40 41 42namespace android { 43// ---------------------------------------------------------------------------- 44 45AudioHardware::AudioHardware() : 46 mInit(false), mMicMute(true), mOutput(0) 47{ 48 mInit = true; 49} 50 51AudioHardware::~AudioHardware() 52{ 53 closeOutputStream((AudioStreamOut*)mOutput); 54 mInit = false; 55} 56 57status_t AudioHardware::initCheck() 58{ 59 return mInit ? NO_ERROR : NO_INIT; 60} 61 62AudioStreamOut* AudioHardware::openOutputStream( 63 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status) 64{ 65 { // scope for the lock 66 Mutex::Autolock lock(mLock); 67 68 // only one output stream allowed 69 if (mOutput) { 70 if (status) { 71 *status = INVALID_OPERATION; 72 } 73 return 0; 74 } 75 76 AudioStreamOutQ5V2* out = new AudioStreamOutQ5V2(); 77 78 status_t rc = out->set(this, devices, format, channels, sampleRate); 79 if (rc) { 80 *status = rc; 81 } 82 if (rc == NO_ERROR) { 83 mOutput = out; 84 } else { 85 delete out; 86 } 87 } 88 return mOutput; 89} 90 91void AudioHardware::closeOutputStream(AudioStreamOut* out) { 92 Mutex::Autolock lock(mLock); 93 if (mOutput == 0 || mOutput != out) { 94 ALOGW("Attempt to close invalid output stream"); 95 } 96 else { 97 delete mOutput; 98 mOutput = 0; 99 } 100} 101 102AudioStreamIn* AudioHardware::openInputStream( 103 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status, 104 AudioSystem::audio_in_acoustics acoustic_flags) 105{ 106 return 0; 107} 108 109void AudioHardware::closeInputStream(AudioStreamIn* in) { 110} 111 112status_t AudioHardware::setMode(int mode) 113{ 114 return NO_ERROR; 115} 116 117status_t AudioHardware::setMicMute(bool state) 118{ 119 return NO_ERROR; 120} 121 122status_t AudioHardware::getMicMute(bool* state) 123{ 124 *state = mMicMute; 125 return NO_ERROR; 126} 127 128status_t AudioHardware::setParameters(const String8& keyValuePairs) 129{ 130 return NO_ERROR; 131} 132 133String8 AudioHardware::getParameters(const String8& keys) 134{ 135 AudioParameter request = AudioParameter(keys); 136 AudioParameter reply = AudioParameter(); 137 138 ALOGV("getParameters() %s", keys.string()); 139 140 return reply.toString(); 141} 142 143size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) 144{ 145 return 4096; 146} 147 148status_t AudioHardware::setVoiceVolume(float v) 149{ 150 return NO_ERROR; 151} 152 153status_t AudioHardware::setMasterVolume(float v) 154{ 155 ALOGI("Set master volume to %f.\n", v); 156 // We return an error code here to let the audioflinger do in-software 157 // volume on top of the maximum volume that we set through the SND API. 158 // return error - software mixer will handle it 159 return -1; 160} 161 162status_t AudioHardware::dump(int fd, const Vector<String16>& args) 163{ 164 return NO_ERROR; 165} 166 167AudioHardware::AudioStreamOutQ5V2::AudioStreamOutQ5V2() : 168 mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true), 169 mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS), mSampleRate(AUDIO_HW_OUT_SAMPLERATE), 170 mBufferSize(AUDIO_HW_OUT_BUFSZ) 171{ 172} 173 174status_t AudioHardware::AudioStreamOutQ5V2::set( 175 AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate) 176{ 177 int lFormat = pFormat ? *pFormat : 0; 178 uint32_t lChannels = pChannels ? *pChannels : 0; 179 uint32_t lRate = pRate ? *pRate : 0; 180 181 mHardware = hw; 182 mDevices = devices; 183 184 // fix up defaults 185 if (lFormat == 0) lFormat = format(); 186 if (lChannels == 0) lChannels = channels(); 187 if (lRate == 0) lRate = sampleRate(); 188 189 // check values 190 if ((lFormat != format()) || 191 (lChannels != channels()) || 192 (lRate != sampleRate())) { 193 if (pFormat) *pFormat = format(); 194 if (pChannels) *pChannels = channels(); 195 if (pRate) *pRate = sampleRate(); 196 return BAD_VALUE; 197 } 198 199 if (pFormat) *pFormat = lFormat; 200 if (pChannels) *pChannels = lChannels; 201 if (pRate) *pRate = lRate; 202 203 mChannels = lChannels; 204 mSampleRate = lRate; 205 mBufferSize = 4096; 206 207 return NO_ERROR; 208} 209 210AudioHardware::AudioStreamOutQ5V2::~AudioStreamOutQ5V2() 211{ 212 standby(); 213} 214 215ssize_t AudioHardware::AudioStreamOutQ5V2::write(const void* buffer, size_t bytes) 216{ 217 // ALOGD("AudioStreamOutQ5V2::write(%p, %u)", buffer, bytes); 218 status_t status = NO_INIT; 219 size_t count = bytes; 220 const uint8_t* p = static_cast<const uint8_t*>(buffer); 221 222 if (mStandby) { 223 ALOGV("open pcm_out driver"); 224 status = ::open("/dev/msm_pcm_out", O_RDWR); 225 if (status < 0) { 226 LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno); 227 goto Error; 228 } 229 mFd = status; 230 231 // configuration 232 ALOGV("get config"); 233 struct msm_audio_config config; 234 status = ioctl(mFd, AUDIO_GET_CONFIG, &config); 235 if (status < 0) { 236 LOGE("Cannot read pcm_out config"); 237 goto Error; 238 } 239 240 ALOGV("set pcm_out config"); 241 config.channel_count = AudioSystem::popCount(channels()); 242 config.sample_rate = mSampleRate; 243 config.buffer_size = mBufferSize; 244 config.buffer_count = AUDIO_HW_NUM_OUT_BUF; 245// config.codec_type = CODEC_TYPE_PCM; 246 status = ioctl(mFd, AUDIO_SET_CONFIG, &config); 247 if (status < 0) { 248 LOGE("Cannot set config"); 249 goto Error; 250 } 251 252 ALOGV("buffer_size: %u", config.buffer_size); 253 ALOGV("buffer_count: %u", config.buffer_count); 254 ALOGV("channel_count: %u", config.channel_count); 255 ALOGV("sample_rate: %u", config.sample_rate); 256 257#if 0 258 status = ioctl(mFd, AUDIO_START, &acdb_id); 259 if (status < 0) { 260 LOGE("Cannot start pcm playback"); 261 goto Error; 262 } 263 264 status = ioctl(mFd, AUDIO_SET_VOLUME, &stream_volume); 265 if (status < 0) { 266 LOGE("Cannot start pcm playback"); 267 goto Error; 268 } 269#endif 270 mStandby = false; 271 } 272 273 while (count) { 274 ssize_t written = ::write(mFd, p, count); 275 if (written >= 0) { 276 count -= written; 277 p += written; 278 } else { 279 if (errno != EAGAIN) return written; 280 mRetryCount++; 281 ALOGW("EAGAIN - retry"); 282 } 283 } 284 285 return bytes; 286 287Error: 288 if (mFd >= 0) { 289 ::close(mFd); 290 mFd = -1; 291 } 292 // Simulate audio output timing in case of error 293 usleep(bytes * 1000000 / frameSize() / sampleRate()); 294 295 return status; 296} 297 298status_t AudioHardware::AudioStreamOutQ5V2::standby() 299{ 300 status_t status = NO_ERROR; 301 if (!mStandby && mFd >= 0) { 302 ::close(mFd); 303 mFd = -1; 304 } 305 mStandby = true; 306 ALOGI("AudioHardware pcm playback is going to standby."); 307 return status; 308} 309 310status_t AudioHardware::AudioStreamOutQ5V2::dump(int fd, const Vector<String16>& args) 311{ 312 return NO_ERROR; 313} 314 315bool AudioHardware::AudioStreamOutQ5V2::checkStandby() 316{ 317 return mStandby; 318} 319 320status_t AudioHardware::AudioStreamOutQ5V2::setParameters(const String8& keyValuePairs) 321{ 322 return NO_ERROR; 323} 324 325String8 AudioHardware::AudioStreamOutQ5V2::getParameters(const String8& keys) 326{ 327 AudioParameter param = AudioParameter(keys); 328 ALOGV("AudioStreamOutQ5V2::getParameters() %s", param.toString().string()); 329 return param.toString(); 330} 331 332status_t AudioHardware::AudioStreamOutQ5V2::getRenderPosition(uint32_t *dspFrames) 333{ 334 return INVALID_OPERATION; 335} 336 337extern "C" AudioHardwareInterface* createAudioHardware(void) { 338 return new AudioHardware(); 339} 340 341}; // namespace android 342