Loading libs/audioflinger/A2dpAudioInterface.cpp +31 −20 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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( Loading Loading @@ -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; size_t remaining = bytes; status_t status = init(); if (status < 0) goto Error; } a2dp_set_sink(mData, mA2dpAddress); } while (remaining > 0) { status = a2dp_write(mData, buffer, remaining); Loading @@ -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) Loading @@ -212,14 +223,14 @@ 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); } return NO_ERROR; } Loading libs/audioflinger/A2dpAudioInterface.h +3 −2 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -96,9 +97,9 @@ private: int mRetryCount; char mA2dpAddress[20]; void* mData; Mutex mLock; }; Mutex mLock; A2dpAudioStreamOut* mOutput; }; Loading libs/audioflinger/AudioFlinger.cpp +156 −153 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -236,8 +269,12 @@ status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args) const size_t SIZE = 256; char buffer[SIZE]; String8 result; int hardwareStatus = mHardwareStatus; snprintf(buffer, SIZE, "Hardware status: %d\n", 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; Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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: Loading Loading @@ -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 Loading Loading @@ -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()); Loading @@ -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) Loading Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading Loading @@ -1104,10 +1102,10 @@ 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); } } } Loading Loading @@ -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, Loading @@ -1218,8 +1216,6 @@ sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack( goto Exit; } { Mutex::Autolock _l(mLock); if (mSampleRate == 0) { LOGE("Audio driver not initialized."); Loading @@ -1230,13 +1226,11 @@ sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack( 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; } Exit: if(status) { Loading @@ -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)) { Loading @@ -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; Loading @@ -1298,7 +1294,7 @@ void AudioFlinger::MixerThread::putTracks( int j = activeTracks.indexOf(t); if (j >= 0) { addActiveTrack(t); addActiveTrack_l(t); } } } Loading Loading @@ -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 Loading @@ -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); Loading @@ -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); Loading @@ -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); } Loading @@ -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, Loading @@ -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"); Loading Loading @@ -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, Loading @@ -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) Loading Loading @@ -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 Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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, Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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 // 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; Loading Loading @@ -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) { Loading Loading
libs/audioflinger/A2dpAudioInterface.cpp +31 −20 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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( Loading Loading @@ -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; size_t remaining = bytes; status_t status = init(); if (status < 0) goto Error; } a2dp_set_sink(mData, mA2dpAddress); } while (remaining > 0) { status = a2dp_write(mData, buffer, remaining); Loading @@ -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) Loading @@ -212,14 +223,14 @@ 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); } return NO_ERROR; } Loading
libs/audioflinger/A2dpAudioInterface.h +3 −2 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -96,9 +97,9 @@ private: int mRetryCount; char mA2dpAddress[20]; void* mData; Mutex mLock; }; Mutex mLock; A2dpAudioStreamOut* mOutput; }; Loading
libs/audioflinger/AudioFlinger.cpp +156 −153 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -236,8 +269,12 @@ status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args) const size_t SIZE = 256; char buffer[SIZE]; String8 result; int hardwareStatus = mHardwareStatus; snprintf(buffer, SIZE, "Hardware status: %d\n", 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; Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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: Loading Loading @@ -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 Loading Loading @@ -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()); Loading @@ -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) Loading Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading Loading @@ -1104,10 +1102,10 @@ 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); } } } Loading Loading @@ -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, Loading @@ -1218,8 +1216,6 @@ sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack( goto Exit; } { Mutex::Autolock _l(mLock); if (mSampleRate == 0) { LOGE("Audio driver not initialized."); Loading @@ -1230,13 +1226,11 @@ sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack( 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; } Exit: if(status) { Loading @@ -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)) { Loading @@ -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; Loading @@ -1298,7 +1294,7 @@ void AudioFlinger::MixerThread::putTracks( int j = activeTracks.indexOf(t); if (j >= 0) { addActiveTrack(t); addActiveTrack_l(t); } } } Loading Loading @@ -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 Loading @@ -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); Loading @@ -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); Loading @@ -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); } Loading @@ -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, Loading @@ -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"); Loading Loading @@ -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, Loading @@ -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) Loading Loading @@ -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 Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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, Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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 // 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; Loading Loading @@ -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) { Loading