auto import from //branches/cupcake/...@137197
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 @@
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 @@
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 @@
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 @@
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::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 @@
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 @@
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 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 @@
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 @@
#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 @@
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 @@
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 @@
if (mAudioHardware) {
mAudioHardware->dumpState(fd, args);
}
+ if (locked) mLock.unlock();
}
return NO_ERROR;
}
@@ -320,18 +365,19 @@
}
#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 @@
#ifdef WITH_A2DP
mA2dpMixerThread->setMasterVolume(value);
#endif
-
+
return NO_ERROR;
}
@@ -436,7 +482,7 @@
if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
enableA2dp = true;
}
- setA2dpEnabled(enableA2dp);
+ setA2dpEnabled_l(enableA2dp);
LOGV("setOutput done\n");
}
#endif
@@ -704,46 +750,6 @@
}
}
-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 @@
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 @@
LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);
} else {
LOGE("mForcedSpeakerCount is already zero");
- }
+ }
}
break;
case CHECK_ROUTE_RESTORE_TIME:
@@ -946,20 +944,20 @@
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 @@
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 @@
#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 @@
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 @@
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,26 +1216,22 @@
goto Exit;
}
- {
- Mutex::Autolock _l(mLock);
- 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;
+ 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) {
+ lStatus = NO_MEMORY;
+ goto Exit;
+ }
+ mTracks.add(track);
+ lStatus = NO_ERROR;
+
Exit:
if(status) {
*status = lStatus;
@@ -1245,12 +1239,13 @@
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 @@
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 @@
int j = activeTracks.indexOf(t);
if (j >= 0) {
- addActiveTrack(t);
+ addActiveTrack_l(t);
}
}
}
@@ -1390,10 +1386,10 @@
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 @@
// 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::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 @@
}
}
-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 @@
// ----------------------------------------------------------------------------
+// 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 @@
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 @@
// ----------------------------------------------------------------------------
+// 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()
{
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 @@
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::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::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 @@
// ----------------------------------------------------------------------------
+// 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()
{
- 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 @@
uint32_t flags,
status_t *status)
{
- sp<AudioRecordThread> thread;
sp<MixerThread::RecordTrack> recordTrack;
sp<RecordHandle> recordHandle;
sp<Client> client;
@@ -2227,7 +2229,7 @@
}
// add client to list
- {
+ { // scope for mLock
Mutex::Autolock _l(mLock);
wclient = mClients.valueFor(pid);
if (wclient != NULL) {
@@ -2236,15 +2238,15 @@
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. The record track uses one track in mHardwareMixerThread by convention.
+ 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 and pass to record thread
- 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 @@
} 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 @@
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 @@
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 @@
bool isMusicActive() const;
- sp<Track> createTrack(
+ sp<Track> createTrack_l(
const sp<AudioFlinger::Client>& client,
int streamType,
uint32_t sampleRate,
@@ -468,12 +469,10 @@
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 @@
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 @@
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 @@
AudioHardwareInterface* mA2dpAudioInterface;
sp<AudioRecordThread> mAudioRecordThread;
bool mA2dpEnabled;
- bool mA2dpEnabledReq;
+ bool mNotifyA2dpChange;
mutable int mHardwareStatus;
SortedVector< wp<IBinder> > mNotificationClients;
int mForcedSpeakerCount;