audioflinger: add standby() method to MmapStreamInterface
Bug: 33398120
Test: open/start/stop/close MMAP no IRQ stream for capture and playback
Change-Id: I48ec202a71565f759c441c2a835d8c8190e76334
diff --git a/include/media/MmapStreamInterface.h b/include/media/MmapStreamInterface.h
index 9f3731e..7dbc19e 100644
--- a/include/media/MmapStreamInterface.h
+++ b/include/media/MmapStreamInterface.h
@@ -75,6 +75,7 @@
/**
* Retrieve information on the mmap buffer used for audio samples transfer.
+ * Must be called before any other method after opening the stream or entering standby.
*
* \param[in] min_size_frames minimum buffer size requested. The actual buffer
* size returned in struct audio_mmap_buffer_info can be larger.
@@ -94,6 +95,7 @@
* \param[out] position address at which the mmap read/write position should be returned.
*
* \return OK if the position is successfully returned.
+ * NO_INIT in case of initialization error
* NOT_ENOUGH_DATA if the position cannot be retrieved
* INVALID_OPERATION if called before createMmapBuffer()
*/
@@ -106,6 +108,7 @@
* \param[in] client a Client struct describing the client starting on this stream.
* \param[out] handle unique handle for this instance. Used with stop().
* \return OK in case of success.
+ * NO_INIT in case of initialization error
* INVALID_OPERATION if called out of sequence
*/
virtual status_t start(const Client& client, audio_port_handle_t *handle) = 0;
@@ -116,10 +119,23 @@
*
* \param[in] handle unique handle allocated by start().
* \return OK in case of success.
+ * NO_INIT in case of initialization error
* INVALID_OPERATION if called out of sequence
*/
virtual status_t stop(audio_port_handle_t handle) = 0;
+ /**
+ * Put a stream operating in mmap mode into standby.
+ * Must be called after createMmapBuffer(). Cannot be called if any client is active.
+ * It is recommended to place a mmap stream into standby as often as possible when no client is
+ * active to save power.
+ *
+ * \return OK in case of success.
+ * NO_INIT in case of initialization error
+ * INVALID_OPERATION if called out of sequence
+ */
+ virtual status_t standby() = 0;
+
protected:
// Subclasses can not be constructed directly by clients.
MmapStreamInterface() {}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 44fd512..4a279ea 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -563,6 +563,7 @@
virtual status_t getMmapPosition(struct audio_mmap_position *position);
virtual status_t start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle);
virtual status_t stop(audio_port_handle_t handle);
+ virtual status_t standby();
private:
sp<MmapThread> mThread;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b10e42c..993e76c 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7434,7 +7434,7 @@
{
MmapThread *thread = mThread.get();
// clear our strong reference before disconnecting the thread: the last strong reference
- // will be removed when closeInput/closeOutput is executed upono call from audio policy manager
+ // will be removed when closeInput/closeOutput is executed upon call from audio policy manager
// and the thread removed from mMMapThreads list causing the thread destruction.
mThread.clear();
if (thread != nullptr) {
@@ -7476,6 +7476,14 @@
return mThread->stop(handle);
}
+status_t AudioFlinger::MmapThreadHandle::standby()
+{
+ if (mThread == 0) {
+ return NO_INIT;
+ }
+ return mThread->standby();
+}
+
AudioFlinger::MmapThread::MmapThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
@@ -7484,11 +7492,13 @@
: ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev)
{
+ mStandby = true;
readHalParameters_l();
}
AudioFlinger::MmapThread::~MmapThread()
{
+ releaseWakeLock_l();
}
void AudioFlinger::MmapThread::onFirstRef()
@@ -7528,6 +7538,8 @@
if (mHalStream == 0) {
return NO_INIT;
}
+ mStandby = true;
+ acquireWakeLock();
return mHalStream->createMmapBuffer(minSizeFrames, info);
}
@@ -7542,7 +7554,7 @@
status_t AudioFlinger::MmapThread::start(const MmapStreamInterface::Client& client,
audio_port_handle_t *handle)
{
- ALOGV("%s clientUid %d", __FUNCTION__, client.clientUid);
+ ALOGV("%s clientUid %d mStandby %d", __FUNCTION__, client.clientUid, mStandby);
if (mHalStream == 0) {
return NO_INIT;
}
@@ -7556,6 +7568,7 @@
mHalStream->start();
portId = mPortId;
sessionId = mSessionId;
+ mStandby = false;
} else {
// for other tracks than first one, get a new port ID from APM.
sessionId = (audio_session_t)mAudioFlinger->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
@@ -7613,6 +7626,8 @@
} else {
AudioSystem::releaseInput(mId, sessionId);
}
+ } else {
+ mHalStream->stop();
}
return PERMISSION_DENIED;
}
@@ -7632,14 +7647,13 @@
broadcast_l();
- ALOGV("%s DONE handle %d", __FUNCTION__, portId);
+ ALOGV("%s DONE handle %d stream %p", __FUNCTION__, portId, mHalStream.get());
return NO_ERROR;
}
status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
{
-
ALOGV("%s handle %d", __FUNCTION__, handle);
if (mHalStream == 0) {
@@ -7685,6 +7699,22 @@
return NO_ERROR;
}
+status_t AudioFlinger::MmapThread::standby()
+{
+ ALOGV("%s", __FUNCTION__);
+
+ if (mHalStream == 0) {
+ return NO_INIT;
+ }
+ if (mActiveTracks.size() != 0) {
+ return INVALID_OPERATION;
+ }
+ mHalStream->standby();
+ mStandby = true;
+ releaseWakeLock();
+ return NO_ERROR;
+}
+
void AudioFlinger::MmapThread::readHalParameters_l()
{
@@ -7701,8 +7731,6 @@
bool AudioFlinger::MmapThread::threadLoop()
{
- acquireWakeLock();
-
checkSilentMode_l();
const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
@@ -7724,18 +7752,10 @@
break;
}
- bool wakelockReleased = false;
- if (mActiveTracks.size() == 0) {
- releaseWakeLock_l();
- wakelockReleased = true;
- }
// wait until we have something to do...
ALOGV("%s going to sleep", myName.string());
mWaitWorkCV.wait(mLock);
ALOGV("%s waking up", myName.string());
- if (wakelockReleased) {
- acquireWakeLock_l();
- }
checkSilentMode_l();
@@ -7768,8 +7788,6 @@
mStandby = true;
}
- releaseWakeLock();
-
ALOGV("Thread %p type %d exiting", this, mType);
return false;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0a17a8e..422eeb5 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1540,6 +1540,7 @@
status_t getMmapPosition(struct audio_mmap_position *position);
status_t start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle);
status_t stop(audio_port_handle_t handle);
+ status_t standby();
// RefBase
virtual void onFirstRef();
@@ -1549,6 +1550,7 @@
virtual void threadLoop_exit();
virtual void threadLoop_standby();
+ virtual bool shouldStandby_l() { return false; }
virtual status_t initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; }
virtual size_t frameCount() const { return mFrameCount; }