diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-09 11:52:12 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-09 11:52:12 -0700 |
commit | b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54 (patch) | |
tree | e167affc928677f3dd70e173150a77e3943e97a9 /libs | |
parent | f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2 (diff) | |
download | frameworks_base-b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54.zip frameworks_base-b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54.tar.gz frameworks_base-b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54.tar.bz2 |
auto import from //branches/cupcake/...@137197
Diffstat (limited to 'libs')
-rw-r--r-- | libs/audioflinger/A2dpAudioInterface.cpp | 51 | ||||
-rw-r--r-- | libs/audioflinger/A2dpAudioInterface.h | 5 | ||||
-rw-r--r-- | libs/audioflinger/AudioFlinger.cpp | 309 | ||||
-rw-r--r-- | libs/audioflinger/AudioFlinger.h | 40 |
4 files changed, 208 insertions, 197 deletions
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp index eb00f8c..2974e32 100644 --- a/libs/audioflinger/A2dpAudioInterface.cpp +++ b/libs/audioflinger/A2dpAudioInterface.cpp @@ -48,7 +48,6 @@ AudioStreamOut* A2dpAudioInterface::openOutputStream( int format, int channelCount, uint32_t sampleRate, status_t *status) { LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate); - Mutex::Autolock lock(mLock); status_t err = 0; // only one output stream allowed @@ -134,7 +133,8 @@ A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() : mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL) { // use any address by default - strncpy(mA2dpAddress, "00:00:00:00:00:00", sizeof(mA2dpAddress)); + strcpy(mA2dpAddress, "00:00:00:00:00:00"); + init(); } status_t A2dpAudioInterface::A2dpAudioStreamOut::set( @@ -163,18 +163,12 @@ A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut() ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes) { - status_t status = NO_INIT; - size_t remaining = bytes; + Mutex::Autolock lock(mLock); - if (!mData) { - status = a2dp_init(44100, 2, &mData); - if (status < 0) { - LOGE("a2dp_init failed err: %d\n", status); - mData = NULL; - goto Error; - } - a2dp_set_sink(mData, mA2dpAddress); - } + size_t remaining = bytes; + status_t status = init(); + if (status < 0) + goto Error; while (remaining > 0) { status = a2dp_write(mData, buffer, remaining); @@ -197,10 +191,27 @@ Error: return status; } +status_t A2dpAudioInterface::A2dpAudioStreamOut::init() +{ + if (!mData) { + status_t status = a2dp_init(44100, 2, &mData); + if (status < 0) { + LOGE("a2dp_init failed err: %d\n", status); + mData = NULL; + return status; + } + a2dp_set_sink(mData, mA2dpAddress); + } + + return 0; +} + status_t A2dpAudioInterface::A2dpAudioStreamOut::standby() { int result = 0; + Mutex::Autolock lock(mLock); + if (!mStandby) { result = a2dp_stop(mData); if (result == 0) @@ -212,15 +223,15 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::standby() status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address) { - if (strlen(address) < sizeof(mA2dpAddress)) + Mutex::Autolock lock(mLock); + + if (strlen(address) != strlen("00:00:00:00:00:00")) return -EINVAL; - if (strcmp(address, mA2dpAddress)) { - strcpy(mA2dpAddress, address); - if (mData) - a2dp_set_sink(mData, mA2dpAddress); - } - + strcpy(mA2dpAddress, address); + if (mData) + a2dp_set_sink(mData, mA2dpAddress); + return NO_ERROR; } diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h index a56e8a0..99614dc 100644 --- a/libs/audioflinger/A2dpAudioInterface.h +++ b/libs/audioflinger/A2dpAudioInterface.h @@ -82,11 +82,12 @@ private: virtual status_t setVolume(float volume) { return INVALID_OPERATION; } virtual ssize_t write(const void* buffer, size_t bytes); status_t standby(); - status_t close(); virtual status_t dump(int fd, const Vector<String16>& args); private: friend class A2dpAudioInterface; + status_t init(); + status_t close(); status_t setAddress(const char* address); private: @@ -96,9 +97,9 @@ private: int mRetryCount; char mA2dpAddress[20]; void* mData; + Mutex mLock; }; - Mutex mLock; A2dpAudioStreamOut* mOutput; }; diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 92c40e9..440778d 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -71,6 +71,9 @@ static const int8_t kMaxTrackStartupRetries = 50; static const int kStartSleepTime = 30000; static const int kStopSleepTime = 30000; +static const int kDumpLockRetries = 50; +static const int kDumpLockSleep = 20000; + // Maximum number of pending buffers allocated by OutputTrack::write() static const uint8_t kMaxOutputTrackBuffers = 5; @@ -115,8 +118,7 @@ static bool settingsAllowed() { AudioFlinger::AudioFlinger() : BnAudioFlinger(), - mAudioHardware(0), mA2dpAudioInterface(0), - mA2dpEnabled(false), mA2dpEnabledReq(false), + mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false), mForcedSpeakerCount(0), mForcedRoute(0), mRouteRestoreTime(0), mMusicMuteSaved(false) { mHardwareStatus = AUDIO_HW_IDLE; @@ -190,13 +192,44 @@ AudioFlinger::~AudioFlinger() #ifdef WITH_A2DP -void AudioFlinger::setA2dpEnabled(bool enable) +// setA2dpEnabled_l() must be called with AudioFlinger::mLock held +void AudioFlinger::setA2dpEnabled_l(bool enable) { + SortedVector < sp<MixerThread::Track> > tracks; + SortedVector < wp<MixerThread::Track> > activeTracks; + LOGV_IF(enable, "set output to A2DP\n"); LOGV_IF(!enable, "set output to hardware audio\n"); - mA2dpEnabledReq = enable; - mA2dpMixerThread->wakeUp(); + // Transfer tracks playing on MUSIC stream from one mixer to the other + if (enable) { + mHardwareMixerThread->getTracks_l(tracks, activeTracks); + mA2dpMixerThread->putTracks_l(tracks, activeTracks); + } else { + mA2dpMixerThread->getTracks_l(tracks, activeTracks); + mHardwareMixerThread->putTracks_l(tracks, activeTracks); + } + mA2dpEnabled = enable; + mNotifyA2dpChange = true; + mWaitWorkCV.broadcast(); +} + +// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held +void AudioFlinger::checkA2dpEnabledChange_l() +{ + if (mNotifyA2dpChange) { + // Notify AudioSystem of the A2DP activation/deactivation + size_t size = mNotificationClients.size(); + for (size_t i = 0; i < size; i++) { + sp<IBinder> binder = mNotificationClients.itemAt(i).promote(); + if (binder != NULL) { + LOGV("Notifying output change to client %p", binder.get()); + sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder); + client->a2dpEnabledChanged(mA2dpEnabled); + } + } + mNotifyA2dpChange = false; + } } #endif // WITH_A2DP @@ -236,8 +269,12 @@ status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args) const size_t SIZE = 256; char buffer[SIZE]; String8 result; - - snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus); + int hardwareStatus = mHardwareStatus; + + if (hardwareStatus == AUDIO_HW_IDLE && mHardwareMixerThread->mStandby) { + hardwareStatus = AUDIO_HW_STANDBY; + } + snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus); result.append(buffer); write(fd, result.string(), result.size()); return NO_ERROR; @@ -262,7 +299,14 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) if (checkCallingPermission(String16("android.permission.DUMP")) == false) { dumpPermissionDenial(fd, args); } else { - AutoMutex lock(&mLock); + bool locked = false; + for (int i = 0; i < kDumpLockRetries; ++i) { + if (mLock.tryLock() == NO_ERROR) { + locked = true; + break; + } + usleep(kDumpLockSleep); + } dumpClients(fd, args); dumpInternals(fd, args); @@ -277,6 +321,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) if (mAudioHardware) { mAudioHardware->dumpState(fd, args); } + if (locked) mLock.unlock(); } return NO_ERROR; } @@ -320,18 +365,19 @@ sp<IAudioTrack> AudioFlinger::createTrack( } #ifdef WITH_A2DP if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) { - track = mA2dpMixerThread->createTrack(client, streamType, sampleRate, format, + track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer, &lStatus); } else #endif { - track = mHardwareMixerThread->createTrack(client, streamType, sampleRate, format, + track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer, &lStatus); } - if (track != NULL) { - trackHandle = new TrackHandle(track); - lStatus = NO_ERROR; - } + } + if (lStatus == NO_ERROR) { + trackHandle = new TrackHandle(track); + } else { + track.clear(); } Exit: @@ -409,7 +455,7 @@ status_t AudioFlinger::setMasterVolume(float value) #ifdef WITH_A2DP mA2dpMixerThread->setMasterVolume(value); #endif - + return NO_ERROR; } @@ -436,7 +482,7 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) { enableA2dp = true; } - setA2dpEnabled(enableA2dp); + setA2dpEnabled_l(enableA2dp); LOGV("setOutput done\n"); } #endif @@ -704,46 +750,6 @@ void AudioFlinger::binderDied(const wp<IBinder>& who) { } } -void AudioFlinger::handleOutputSwitch() -{ - if (mA2dpEnabled != mA2dpEnabledReq) - { - Mutex::Autolock _l(mLock); - - if (mA2dpEnabled != mA2dpEnabledReq) - { - mA2dpEnabled = mA2dpEnabledReq; - SortedVector < sp<MixerThread::Track> > tracks; - SortedVector < wp<MixerThread::Track> > activeTracks; - - // We hold mA2dpMixerThread mLock already - Mutex::Autolock _l(mHardwareMixerThread->mLock); - - // Transfer tracks playing on MUSIC stream from one mixer to the other - if (mA2dpEnabled) { - mHardwareMixerThread->getTracks(tracks, activeTracks); - mA2dpMixerThread->putTracks(tracks, activeTracks); - } else { - mA2dpMixerThread->getTracks(tracks, activeTracks); - mHardwareMixerThread->putTracks(tracks, activeTracks); - } - - // Notify AudioSystem of the A2DP activation/deactivation - size_t size = mNotificationClients.size(); - for (size_t i = 0; i < size; i++) { - sp<IBinder> binder = mNotificationClients.itemAt(i).promote(); - if (binder != NULL) { - LOGV("Notifying output change to client %p", binder.get()); - sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder); - client->a2dpEnabledChanged(mA2dpEnabled); - } - } - - mHardwareMixerThread->wakeUp(); - } - } -} - void AudioFlinger::removeClient(pid_t pid) { LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid()); @@ -751,17 +757,9 @@ void AudioFlinger::removeClient(pid_t pid) mClients.removeItem(pid); } -void AudioFlinger::wakeUp() -{ - mHardwareMixerThread->wakeUp(); -#ifdef WITH_A2DP - mA2dpMixerThread->wakeUp(); -#endif // WITH_A2DP -} - bool AudioFlinger::isA2dpEnabled() const { - return mA2dpEnabledReq; + return mA2dpEnabled; } void AudioFlinger::handleForcedSpeakerRoute(int command) @@ -803,7 +801,7 @@ void AudioFlinger::handleForcedSpeakerRoute(int command) LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount); } else { LOGE("mForcedSpeakerCount is already zero"); - } + } } break; case CHECK_ROUTE_RESTORE_TIME: @@ -946,20 +944,20 @@ bool AudioFlinger::MixerThread::threadLoop() do { enabledTracks = 0; - { // scope for the mLock + { // scope for the AudioFlinger::mLock - Mutex::Autolock _l(mLock); + Mutex::Autolock _l(mAudioFlinger->mLock); #ifdef WITH_A2DP - if (mOutputType == AudioSystem::AUDIO_OUTPUT_A2DP) { - mAudioFlinger->handleOutputSwitch(); - } if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) { if (outputTrackActive) { + mAudioFlinger->mLock.unlock(); mOutputTrack->stop(); + mAudioFlinger->mLock.lock(); outputTrackActive = false; } } + mAudioFlinger->checkA2dpEnabledChange_l(); #endif const SortedVector< wp<Track> >& activeTracks = mActiveTracks; @@ -968,7 +966,6 @@ bool AudioFlinger::MixerThread::threadLoop() if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) { // wait until we have something to do... LOGV("Audio hardware entering standby, output %d\n", mOutputType); -// mAudioFlinger->mHardwareStatus = AUDIO_HW_STANDBY; if (!mStandby) { mOutput->standby(); mStandby = true; @@ -976,17 +973,18 @@ bool AudioFlinger::MixerThread::threadLoop() #ifdef WITH_A2DP if (outputTrackActive) { + mAudioFlinger->mLock.unlock(); mOutputTrack->stop(); + mAudioFlinger->mLock.lock(); outputTrackActive = false; } #endif if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE); } -// mHardwareStatus = AUDIO_HW_IDLE; // we're about to wait, flush the binder command buffer IPCThreadState::self()->flushCommands(); - mWaitWorkCV.wait(mLock); + mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock); LOGV("Audio hardware exiting standby, output %d\n", mOutputType); if (mMasterMute == false) { @@ -1104,13 +1102,13 @@ bool AudioFlinger::MixerThread::threadLoop() if (UNLIKELY(count)) { for (size_t i=0 ; i<count ; i++) { const sp<Track>& track = tracksToRemove[i]; - removeActiveTrack(track); + removeActiveTrack_l(track); if (track->isTerminated()) { mTracks.remove(track); - deleteTrackName(track->mName); + deleteTrackName_l(track->mName); } } - } + } } if (LIKELY(enabledTracks)) { @@ -1197,8 +1195,8 @@ void AudioFlinger::MixerThread::onFirstRef() run(buffer, ANDROID_PRIORITY_URGENT_AUDIO); } - -sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack( +// MixerThread::createTrack_l() must be called with AudioFlinger::mLock held +sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack_l( const sp<AudioFlinger::Client>& client, int streamType, uint32_t sampleRate, @@ -1218,25 +1216,21 @@ sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack( goto Exit; } - { - Mutex::Autolock _l(mLock); - if (mSampleRate == 0) { - LOGE("Audio driver not initialized."); - lStatus = NO_INIT; - goto Exit; - } + if (mSampleRate == 0) { + LOGE("Audio driver not initialized."); + lStatus = NO_INIT; + goto Exit; + } - track = new Track(this, client, streamType, sampleRate, format, - channelCount, frameCount, sharedBuffer); - if (track->getCblk() == NULL) { - track.clear(); - lStatus = NO_MEMORY; - goto Exit; - } - mTracks.add(track); - lStatus = NO_ERROR; + track = new Track(this, client, streamType, sampleRate, format, + channelCount, frameCount, sharedBuffer); + if (track->getCblk() == NULL) { + lStatus = NO_MEMORY; + goto Exit; } + mTracks.add(track); + lStatus = NO_ERROR; Exit: if(status) { @@ -1245,12 +1239,13 @@ Exit: return track; } -void AudioFlinger::MixerThread::getTracks( +// getTracks_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::getTracks_l( SortedVector < sp<Track> >& tracks, SortedVector < wp<Track> >& activeTracks) { size_t size = mTracks.size(); - LOGV ("MixerThread::getTracks() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType, mTracks.size(), mActiveTracks.size()); + LOGV ("MixerThread::getTracks_l() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType, mTracks.size(), mActiveTracks.size()); for (size_t i = 0; i < size; i++) { sp<Track> t = mTracks[i]; if (AudioSystem::routedToA2dpOutput(t->mStreamType)) { @@ -1267,28 +1262,29 @@ void AudioFlinger::MixerThread::getTracks( size = activeTracks.size(); for (size_t i = 0; i < size; i++) { - removeActiveTrack(activeTracks[i]); + removeActiveTrack_l(activeTracks[i]); } size = tracks.size(); for (size_t i = 0; i < size; i++) { sp<Track> t = tracks[i]; mTracks.remove(t); - deleteTrackName(t->name()); + deleteTrackName_l(t->name()); } } -void AudioFlinger::MixerThread::putTracks( +// putTracks_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::putTracks_l( SortedVector < sp<Track> >& tracks, SortedVector < wp<Track> >& activeTracks) { - LOGV ("MixerThread::putTracks() for output %d, tracks.size %d, activeTracks.size %d", mOutputType, tracks.size(), activeTracks.size()); + LOGV ("MixerThread::putTracks_l() for output %d, tracks.size %d, activeTracks.size %d", mOutputType, tracks.size(), activeTracks.size()); size_t size = tracks.size(); for (size_t i = 0; i < size ; i++) { sp<Track> t = tracks[i]; - int name = getTrackName(); + int name = getTrackName_l(); if (name < 0) return; @@ -1298,7 +1294,7 @@ void AudioFlinger::MixerThread::putTracks( int j = activeTracks.indexOf(t); if (j >= 0) { - addActiveTrack(t); + addActiveTrack_l(t); } } } @@ -1390,10 +1386,10 @@ bool AudioFlinger::MixerThread::isMusicActive() const return false; } -status_t AudioFlinger::MixerThread::addTrack(const sp<Track>& track) +// addTrack_l() must be called with AudioFlinger::mLock held +status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track) { status_t status = ALREADY_EXISTS; - Mutex::Autolock _l(mLock); // here the track could be either new, or restarted // in both cases "unstop" the track @@ -1412,55 +1408,41 @@ status_t AudioFlinger::MixerThread::addTrack(const sp<Track>& track) // effectively get the latency it requested. track->mFillingUpStatus = Track::FS_FILLING; track->mResetDone = false; - addActiveTrack(track); + addActiveTrack_l(track); status = NO_ERROR; } LOGV("mWaitWorkCV.broadcast"); - mWaitWorkCV.broadcast(); + mAudioFlinger->mWaitWorkCV.broadcast(); return status; } -void AudioFlinger::MixerThread::removeTrack(wp<Track> track, int name) +// removeTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name) { - Mutex::Autolock _l(mLock); sp<Track> t = track.promote(); if (t!=NULL && (t->mState <= TrackBase::STOPPED)) { - remove_track_l(track, name); - } -} - -void AudioFlinger::MixerThread::remove_track_l(wp<Track> track, int name) -{ - sp<Track> t = track.promote(); - if (t!=NULL) { t->reset(); + deleteTrackName_l(name); + removeActiveTrack_l(track); + mAudioFlinger->mWaitWorkCV.broadcast(); } - deleteTrackName(name); - removeActiveTrack(track); - mWaitWorkCV.broadcast(); } -void AudioFlinger::MixerThread::destroyTrack(const sp<Track>& track) +// destroyTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track) { - // NOTE: We're acquiring a strong reference on the track before - // acquiring the lock, this is to make sure removing it from - // mTracks won't cause the destructor to be called while the lock is - // held (note that technically, 'track' could be a reference to an item - // in mTracks, which is why we need to do this). - sp<Track> keep(track); - Mutex::Autolock _l(mLock); track->mState = TrackBase::TERMINATED; if (mActiveTracks.indexOf(track) < 0) { LOGV("remove track (%d) and delete from mixer", track->name()); mTracks.remove(track); - deleteTrackName(keep->name()); + deleteTrackName_l(track->name()); } } - -void AudioFlinger::MixerThread::addActiveTrack(const wp<Track>& t) +// addActiveTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t) { mActiveTracks.add(t); @@ -1476,7 +1458,8 @@ void AudioFlinger::MixerThread::addActiveTrack(const wp<Track>& t) } } -void AudioFlinger::MixerThread::removeActiveTrack(const wp<Track>& t) +// removeActiveTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t) { mActiveTracks.remove(t); @@ -1492,12 +1475,14 @@ void AudioFlinger::MixerThread::removeActiveTrack(const wp<Track>& t) } } -int AudioFlinger::MixerThread::getTrackName() +// getTrackName_l() must be called with AudioFlinger::mLock held +int AudioFlinger::MixerThread::getTrackName_l() { return mAudioMixer->getTrackName(); } -void AudioFlinger::MixerThread::deleteTrackName(int name) +// deleteTrackName_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::deleteTrackName_l(int name) { mAudioMixer->deleteTrackName(name); } @@ -1509,6 +1494,7 @@ size_t AudioFlinger::MixerThread::getOutputFrameCount() // ---------------------------------------------------------------------------- +// TrackBase constructor must be called with AudioFlinger::mLock held AudioFlinger::MixerThread::TrackBase::TrackBase( const sp<MixerThread>& mixerThread, const sp<Client>& client, @@ -1529,7 +1515,7 @@ AudioFlinger::MixerThread::TrackBase::TrackBase( mFormat(format), mFlags(flags & ~SYSTEM_FLAGS_MASK) { - mName = mixerThread->getTrackName(); + mName = mixerThread->getTrackName_l(); LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid()); if (mName < 0) { LOGE("no more track names availlable"); @@ -1661,6 +1647,7 @@ void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t // ---------------------------------------------------------------------------- +// Track constructor must be called with AudioFlinger::mLock held AudioFlinger::MixerThread::Track::Track( const sp<MixerThread>& mixerThread, const sp<Client>& client, @@ -1681,13 +1668,26 @@ AudioFlinger::MixerThread::Track::Track( AudioFlinger::MixerThread::Track::~Track() { wp<Track> weak(this); // never create a strong ref from the dtor + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); mState = TERMINATED; - mMixerThread->removeTrack(weak, mName); + mMixerThread->removeTrack_l(weak, mName); } void AudioFlinger::MixerThread::Track::destroy() { - mMixerThread->destroyTrack(this); + // NOTE: destroyTrack_l() can remove a strong reference to this Track + // by removing it from mTracks vector, so there is a risk that this Tracks's + // desctructor is called. As the destructor needs to lock AudioFlinger::mLock, + // we must acquire a strong reference on this Track before locking AudioFlinger::mLock + // here so that the destructor is called only when exiting this function. + // On the other hand, as long as Track::destroy() is only called by + // TrackHandle destructor, the TrackHandle still holds a strong ref on + // this Track with its member mTrack. + sp<Track> keep(this); + { // scope for AudioFlinger::mLock + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); + mMixerThread->destroyTrack_l(this); + } } void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size) @@ -1765,14 +1765,15 @@ bool AudioFlinger::MixerThread::Track::isReady() const { status_t AudioFlinger::MixerThread::Track::start() { LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType); - mMixerThread->addTrack(this); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); + mMixerThread->addTrack_l(this); return NO_ERROR; } void AudioFlinger::MixerThread::Track::stop() { LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType); - Mutex::Autolock _l(mMixerThread->mLock); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); if (mState > STOPPED) { mState = STOPPED; // If the track is not active (PAUSED and buffers full), flush buffers @@ -1786,7 +1787,7 @@ void AudioFlinger::MixerThread::Track::stop() void AudioFlinger::MixerThread::Track::pause() { LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mMixerThread->mLock); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); if (mState == ACTIVE || mState == RESUMING) { mState = PAUSING; LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName); @@ -1796,7 +1797,7 @@ void AudioFlinger::MixerThread::Track::pause() void AudioFlinger::MixerThread::Track::flush() { LOGV("flush(%d)", mName); - Mutex::Autolock _l(mMixerThread->mLock); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); if (mState != STOPPED && mState != PAUSED && mState != PAUSING) { return; } @@ -1840,6 +1841,7 @@ void AudioFlinger::MixerThread::Track::setVolume(float left, float right) // ---------------------------------------------------------------------------- +// RecordTrack constructor must be called with AudioFlinger::mLock held AudioFlinger::MixerThread::RecordTrack::RecordTrack( const sp<MixerThread>& mixerThread, const sp<Client>& client, @@ -1857,7 +1859,8 @@ AudioFlinger::MixerThread::RecordTrack::RecordTrack( AudioFlinger::MixerThread::RecordTrack::~RecordTrack() { - mMixerThread->deleteTrackName(mName); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); + mMixerThread->deleteTrackName_l(mName); } status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) @@ -2183,7 +2186,6 @@ sp<IAudioRecord> AudioFlinger::openRecord( uint32_t flags, status_t *status) { - sp<AudioRecordThread> thread; sp<MixerThread::RecordTrack> recordTrack; sp<RecordHandle> recordHandle; sp<Client> client; @@ -2227,7 +2229,7 @@ sp<IAudioRecord> AudioFlinger::openRecord( } // add client to list - { + { // scope for mLock Mutex::Autolock _l(mLock); wclient = mClients.valueFor(pid); if (wclient != NULL) { @@ -2236,15 +2238,15 @@ sp<IAudioRecord> AudioFlinger::openRecord( client = new Client(this, pid); mClients.add(pid, client); } - } - - // frameCount must be a multiple of input buffer size - inFrameCount = inputBufferSize/channelCount/sizeof(short); - frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount; - // create new record track and pass to record thread - recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate, - format, channelCount, frameCount, flags); + // frameCount must be a multiple of input buffer size + inFrameCount = inputBufferSize/channelCount/sizeof(short); + frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount; + + // create new record track. The record track uses one track in mHardwareMixerThread by convention. + recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate, + format, channelCount, frameCount, flags); + } if (recordTrack->getCblk() == NULL) { recordTrack.clear(); lStatus = NO_MEMORY; @@ -2369,7 +2371,8 @@ bool AudioFlinger::AudioRecordThread::threadLoop() } else if (mRecordTrack != 0) { buffer.frameCount = inFrameCount; - if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) { + if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR && + (int)buffer.frameCount == inFrameCount)) { LOGV("AudioRecordThread read: %d frames", buffer.frameCount); ssize_t bytesRead = input->read(buffer.raw, inBufferSize); if (bytesRead < 0) { diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 77f064b..c505336 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -112,7 +112,7 @@ public: virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); - virtual void wakeUp(); + virtual void wakeUp() { mWaitWorkCV.broadcast(); } // IBinder::DeathRecipient virtual void binderDied(const wp<IBinder>& who); @@ -161,7 +161,8 @@ private: void doSetOutput(int outputType); #ifdef WITH_A2DP - void setA2dpEnabled(bool enable); + void setA2dpEnabled_l(bool enable); + void checkA2dpEnabledChange_l(); #endif static bool streamForcedToSpeaker(int streamType); @@ -459,7 +460,7 @@ private: bool isMusicActive() const; - sp<Track> createTrack( + sp<Track> createTrack_l( const sp<AudioFlinger::Client>& client, int streamType, uint32_t sampleRate, @@ -468,12 +469,10 @@ private: int frameCount, const sp<IMemory>& sharedBuffer, status_t *status); - - void wakeUp() { mWaitWorkCV.broadcast(); } - void getTracks(SortedVector < sp<Track> >& tracks, + void getTracks_l(SortedVector < sp<Track> >& tracks, SortedVector < wp<Track> >& activeTracks); - void putTracks(SortedVector < sp<Track> >& tracks, + void putTracks_l(SortedVector < sp<Track> >& tracks, SortedVector < wp<Track> >& activeTracks); void setOuputTrack(OutputTrack *track) { mOutputTrack = track; } @@ -498,22 +497,19 @@ private: MixerThread(const Client&); MixerThread& operator = (const MixerThread&); - status_t addTrack(const sp<Track>& track); - void removeTrack(wp<Track> track, int name); - void remove_track_l(wp<Track> track, int name); - void destroyTrack(const sp<Track>& track); - int getTrackName(); - void deleteTrackName(int name); - void addActiveTrack(const wp<Track>& t); - void removeActiveTrack(const wp<Track>& t); + status_t addTrack_l(const sp<Track>& track); + void removeTrack_l(wp<Track> track, int name); + void destroyTrack_l(const sp<Track>& track); + int getTrackName_l(); + void deleteTrackName_l(int name); + void addActiveTrack_l(const wp<Track>& t); + void removeActiveTrack_l(const wp<Track>& t); size_t getOutputFrameCount(); status_t dumpInternals(int fd, const Vector<String16>& args); status_t dumpTracks(int fd, const Vector<String16>& args); sp<AudioFlinger> mAudioFlinger; - mutable Mutex mLock; - mutable Condition mWaitWorkCV; SortedVector< wp<Track> > mActiveTracks; SortedVector< sp<Track> > mTracks; stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES]; @@ -607,11 +603,11 @@ private: status_t startRecord(MixerThread::RecordTrack* recordTrack); void stopRecord(MixerThread::RecordTrack* recordTrack); - - void handleOutputSwitch(); - mutable Mutex mHardwareLock; - mutable Mutex mLock; + mutable Mutex mHardwareLock; + mutable Mutex mLock; + mutable Condition mWaitWorkCV; + DefaultKeyedVector< pid_t, wp<Client> > mClients; sp<MixerThread> mA2dpMixerThread; @@ -620,7 +616,7 @@ private: AudioHardwareInterface* mA2dpAudioInterface; sp<AudioRecordThread> mAudioRecordThread; bool mA2dpEnabled; - bool mA2dpEnabledReq; + bool mNotifyA2dpChange; mutable int mHardwareStatus; SortedVector< wp<IBinder> > mNotificationClients; int mForcedSpeakerCount; |