diff options
author | Glenn Kasten <gkasten@google.com> | 2013-09-30 14:39:28 -0700 |
---|---|---|
committer | Glenn Kasten <gkasten@google.com> | 2013-12-05 13:47:07 -0800 |
commit | 481fb67a595f23c5b7f5be84b06db9b84a41a42f (patch) | |
tree | 095712959d22a6fdfaa101c262ccad183576cb6d | |
parent | 84acd489b93e04bea7aab06d8abb024eef2576fd (diff) | |
download | frameworks_av-481fb67a595f23c5b7f5be84b06db9b84a41a42f.zip frameworks_av-481fb67a595f23c5b7f5be84b06db9b84a41a42f.tar.gz frameworks_av-481fb67a595f23c5b7f5be84b06db9b84a41a42f.tar.bz2 |
Add RecordThread media.log and deferred deallocation
This change allows a media.log buffer for RecordThread.
Unlike playback threads which stick around forever, the RecordThread comes
and goes for every capture session. This means that the media.log buffer
for a RecordThread would disappear too, and so was useless. Now when a
thread exits, it's associated media.log buffer is just marked for deferred
deallocation. It is only actually freed when the memory is needed.
Other changes:
- Fix bug in unregistering comparison, it was comparing the wrong pointers
- Increased size of log area so we can log for RecordThread also
Change-Id: If45d4c03a793b86390a0112ec3acc5d41b2e3635
-rw-r--r-- | media/libnbaio/NBLog.cpp | 2 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 61 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 6 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 2 |
4 files changed, 57 insertions, 14 deletions
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp index 045bf64..ba8d0b4 100644 --- a/media/libnbaio/NBLog.cpp +++ b/media/libnbaio/NBLog.cpp @@ -441,7 +441,7 @@ void NBLog::Reader::dump(int fd, size_t indent) bool NBLog::Reader::isIMemory(const sp<IMemory>& iMemory) const { - return iMemory.get() == mIMemory.get(); + return iMemory != 0 && mIMemory != 0 && iMemory->pointer() == mIMemory->pointer(); } } // namespace android diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 5cf6ef3..443051c 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -213,6 +213,18 @@ AudioFlinger::~AudioFlinger() audio_hw_device_close(mAudioHwDevs.valueAt(i)->hwDevice()); delete mAudioHwDevs.valueAt(i); } + + // Tell media.log service about any old writers that still need to be unregistered + sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log")); + if (binder != 0) { + sp<IMediaLogService> mediaLogService(interface_cast<IMediaLogService>(binder)); + for (size_t count = mUnregisteredWriters.size(); count > 0; count--) { + sp<IMemory> iMemory(mUnregisteredWriters.top()->getIMemory()); + mUnregisteredWriters.pop(); + mediaLogService->unregisterWriter(iMemory); + } + } + } static const char * const audio_interfaces[] = { @@ -406,16 +418,44 @@ sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid) sp<NBLog::Writer> AudioFlinger::newWriter_l(size_t size, const char *name) { + // If there is no memory allocated for logs, return a dummy writer that does nothing if (mLogMemoryDealer == 0) { return new NBLog::Writer(); } - sp<IMemory> shared = mLogMemoryDealer->allocate(NBLog::Timeline::sharedSize(size)); - sp<NBLog::Writer> writer = new NBLog::Writer(size, shared); sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log")); - if (binder != 0) { - interface_cast<IMediaLogService>(binder)->registerWriter(shared, size, name); + // Similarly if we can't contact the media.log service, also return a dummy writer + if (binder == 0) { + return new NBLog::Writer(); } - return writer; + sp<IMediaLogService> mediaLogService(interface_cast<IMediaLogService>(binder)); + sp<IMemory> shared = mLogMemoryDealer->allocate(NBLog::Timeline::sharedSize(size)); + // If allocation fails, consult the vector of previously unregistered writers + // and garbage-collect one or more them until an allocation succeeds + if (shared == 0) { + Mutex::Autolock _l(mUnregisteredWritersLock); + for (size_t count = mUnregisteredWriters.size(); count > 0; count--) { + { + // Pick the oldest stale writer to garbage-collect + sp<IMemory> iMemory(mUnregisteredWriters[0]->getIMemory()); + mUnregisteredWriters.removeAt(0); + mediaLogService->unregisterWriter(iMemory); + // Now the media.log remote reference to IMemory is gone. When our last local + // reference to IMemory also drops to zero at end of this block, + // the IMemory destructor will deallocate the region from mLogMemoryDealer. + } + // Re-attempt the allocation + shared = mLogMemoryDealer->allocate(NBLog::Timeline::sharedSize(size)); + if (shared != 0) { + goto success; + } + } + // Even after garbage-collecting all old writers, there is still not enough memory, + // so return a dummy writer + return new NBLog::Writer(); + } +success: + mediaLogService->registerWriter(shared, size, name); + return new NBLog::Writer(size, shared); } void AudioFlinger::unregisterWriter(const sp<NBLog::Writer>& writer) @@ -427,13 +467,10 @@ void AudioFlinger::unregisterWriter(const sp<NBLog::Writer>& writer) if (iMemory == 0) { return; } - sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log")); - if (binder != 0) { - interface_cast<IMediaLogService>(binder)->unregisterWriter(iMemory); - // Now the media.log remote reference to IMemory is gone. - // When our last local reference to IMemory also drops to zero, - // the IMemory destructor will deallocate the region from mMemoryDealer. - } + // Rather than removing the writer immediately, append it to a queue of old writers to + // be garbage-collected later. This allows us to continue to view old logs for a while. + Mutex::Autolock _l(mUnregisteredWritersLock); + mUnregisteredWriters.push(writer); } // IAudioFlinger interface diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 9137040..066d5d5 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -235,8 +235,12 @@ public: sp<NBLog::Writer> newWriter_l(size_t size, const char *name); void unregisterWriter(const sp<NBLog::Writer>& writer); private: - static const size_t kLogMemorySize = 10 * 1024; + static const size_t kLogMemorySize = 40 * 1024; sp<MemoryDealer> mLogMemoryDealer; // == 0 when NBLog is disabled + // When a log writer is unregistered, it is done lazily so that media.log can continue to see it + // for as long as possible. The memory is only freed when it is needed for another log writer. + Vector< sp<NBLog::Writer> > mUnregisteredWriters; + Mutex mUnregisteredWritersLock; public: class SyncEvent; diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 7d39822..148644e 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -4404,6 +4404,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, #endif { snprintf(mName, kNameLength, "AudioIn_%X", id); + mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mName); readInputParameters(); } @@ -4411,6 +4412,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::RecordThread::~RecordThread() { + mAudioFlinger->unregisterWriter(mNBLogWriter); delete[] mRsmpInBuffer; delete mResampler; delete[] mRsmpOutBuffer; |