NBLog periodic merging thread
Bug: 35468674
Test: no change in functionality, everything works as before
Change-Id: Id2cea243bc15767ca6803c9505bf23a18411500e
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3d1f268..c0918d4 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -129,6 +129,7 @@
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
+ mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
mPrimaryHardwareDev(NULL),
mAudioHwDevs(NULL),
mHardwareStatus(AUDIO_HW_IDLE),
@@ -163,6 +164,8 @@
mDevicesFactoryHal = DevicesFactoryHalInterface::create();
mEffectsFactoryHal = EffectsFactoryHalInterface::create();
+ mMediaLogNotifier->run("MediaLogNotifier");
+
#ifdef TEE_SINK
char value[PROPERTY_VALUE_MAX];
(void) property_get("ro.debuggable", value, "0");
@@ -1528,6 +1531,41 @@
mAudioFlinger->removeNotificationClient(mPid);
}
+// ----------------------------------------------------------------------------
+AudioFlinger::MediaLogNotifier::MediaLogNotifier()
+ : mPendingRequests(false) {}
+
+
+void AudioFlinger::MediaLogNotifier::requestMerge() {
+ AutoMutex _l(mMutex);
+ mPendingRequests = true;
+ mCond.signal();
+}
+
+bool AudioFlinger::MediaLogNotifier::threadLoop() {
+ // Wait until there are pending requests
+ {
+ AutoMutex _l(mMutex);
+ mPendingRequests = false; // to ignore past requests
+ while (!mPendingRequests) {
+ mCond.wait(mMutex);
+ // TODO may also need an exitPending check
+ }
+ mPendingRequests = false;
+ }
+ // Execute the actual MediaLogService binder call and ignore extra requests for a while
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log"));
+ if (binder != 0) {
+ sp<IMediaLogService> mediaLogService(interface_cast<IMediaLogService>(binder));
+ mediaLogService->requestMergeWakeup();
+ }
+ usleep(kPostTriggerSleepPeriod);
+ return true;
+}
+
+void AudioFlinger::requestLogMerge() {
+ mMediaLogNotifier->requestMerge();
+}
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 44fd512..f9c4ffd 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -472,6 +472,38 @@
const sp<IAudioFlingerClient> mAudioFlingerClient;
};
+ // --- MediaLogNotifier ---
+ // Thread in charge of notifying MediaLogService to start merging.
+ // Receives requests from AudioFlinger's binder activity. It is used to reduce the amount of
+ // binder calls to MediaLogService in case of bursts of AudioFlinger binder calls.
+ class MediaLogNotifier : public Thread {
+ public:
+ MediaLogNotifier();
+
+ // Requests a MediaLogService notification. It's ignored if there has recently been another
+ void requestMerge();
+ private:
+ // Every iteration blocks waiting for a request, then interacts with MediaLogService to
+ // start merging.
+ // As every MediaLogService binder call is expensive, once it gets a request it ignores the
+ // following ones for a period of time.
+ virtual bool threadLoop() override;
+
+ bool mPendingRequests;
+
+ // Mutex and condition variable around mPendingRequests' value
+ Mutex mMutex;
+ Condition mCond;
+
+ // Duration of the sleep period after a processed request
+ static const int kPostTriggerSleepPeriod = 1000000;
+ };
+
+ const sp<MediaLogNotifier> mMediaLogNotifier;
+
+ // This is a helper that is called during incoming binder calls.
+ void requestLogMerge();
+
class TrackHandle;
class RecordHandle;
class RecordThread;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b10e42c..b247b64 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2953,6 +2953,10 @@
#endif
while (!exitPending())
{
+ // Log merge requests are performed during AudioFlinger binder transactions, but
+ // that does not cover audio playback. It's requested here for that reason.
+ mAudioFlinger->requestLogMerge();
+
cpuStats.sample(myName);
Vector< sp<EffectChain> > effectChains;
diff --git a/services/medialog/IMediaLogService.cpp b/services/medialog/IMediaLogService.cpp
index bc445ff..0e9b01e 100644
--- a/services/medialog/IMediaLogService.cpp
+++ b/services/medialog/IMediaLogService.cpp
@@ -29,6 +29,7 @@
enum {
REGISTER_WRITER = IBinder::FIRST_CALL_TRANSACTION,
UNREGISTER_WRITER,
+ REQUEST_MERGE_WAKEUP,
};
class BpMediaLogService : public BpInterface<IMediaLogService>
@@ -57,6 +58,13 @@
// FIXME ignores status
}
+ virtual void requestMergeWakeup() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaLogService::getInterfaceDescriptor());
+ status_t status __unused = remote()->transact(REQUEST_MERGE_WAKEUP, data, &reply);
+ // FIXME ignores status
+ }
+
};
IMPLEMENT_META_INTERFACE(MediaLogService, "android.media.IMediaLogService");
@@ -84,6 +92,12 @@
return NO_ERROR;
}
+ case REQUEST_MERGE_WAKEUP: {
+ CHECK_INTERFACE(IMediaLogService, data, reply);
+ requestMergeWakeup();
+ return NO_ERROR;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 4c81436..aaf1018 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -27,6 +27,23 @@
namespace android {
// static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
+MediaLogService::MediaLogService() :
+ BnMediaLogService(),
+ mMergerShared((NBLog::Shared*) malloc(NBLog::Timeline::sharedSize(kMergeBufferSize))),
+ mMerger(mMergerShared, kMergeBufferSize),
+ mMergeReader(mMergerShared, kMergeBufferSize, mMerger),
+ mMergeThread(new NBLog::MergeThread(mMerger))
+{
+ mMergeThread->run("MergeThread");
+}
+
+MediaLogService::~MediaLogService()
+{
+ mMergeThread->requestExit();
+ mMergeThread->setTimeoutUs(0);
+ mMergeThread->join();
+ free(mMergerShared);
+}
void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name)
{
@@ -111,8 +128,7 @@
mLock.unlock();
}
#endif
-
- mMerger.merge();
+ // FIXME request merge to make sure log is up to date
mMergeReader.dump(fd);
return NO_ERROR;
}
@@ -123,4 +139,8 @@
return BnMediaLogService::onTransact(code, data, reply, flags);
}
+void MediaLogService::requestMergeWakeup() {
+ mMergeThread->wakeup();
+}
+
} // namespace android
diff --git a/services/medialog/MediaLogService.h b/services/medialog/MediaLogService.h
index e934844..c6b99f1 100644
--- a/services/medialog/MediaLogService.h
+++ b/services/medialog/MediaLogService.h
@@ -27,13 +27,8 @@
{
friend class BinderService<MediaLogService>; // for MediaLogService()
public:
- MediaLogService() :
- BnMediaLogService(),
- mMergerShared((NBLog::Shared*) malloc(NBLog::Timeline::sharedSize(kMergeBufferSize))),
- mMerger(mMergerShared, kMergeBufferSize),
- mMergeReader(mMergerShared, kMergeBufferSize, mMerger)
- {ALOGI("Nico creating MergeReader");}
- virtual ~MediaLogService() { free(mMergerShared); }
+ MediaLogService();
+ virtual ~MediaLogService() override;
virtual void onFirstRef() { }
static const char* getServiceName() { return "media.log"; }
@@ -47,6 +42,8 @@
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags);
+ virtual void requestMergeWakeup() override;
+
private:
// Internal dump
@@ -58,10 +55,10 @@
Mutex mLock;
Vector<NBLog::NamedReader> mNamedReaders;
-
NBLog::Shared *mMergerShared;
NBLog::Merger mMerger;
NBLog::MergeReader mMergeReader;
+ const sp<NBLog::MergeThread> mMergeThread;
};
} // namespace android