diff --git a/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h
index 78ea1b596cc37d32f34306dae0f8e9a480a29a09..997439e025c509a81812dce1b7ee0207c57cf60e 100644
--- a/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h
+++ b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h
@@ -32,7 +32,9 @@ public:
RendererState GetStatus() const override;
bool GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) const override;
bool Drain() const override;
+ bool Pause() const override;
bool Stop() const override;
+ bool Flush() const override;
bool Release() const override;
int32_t GetBufferSize(size_t &bufferSize) const override;
diff --git a/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp b/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp
index 87c8fdc3395c8bb6c84057b79b2bc90238cf48e3..df37e8ca5352bc0455014b3b94c9787ef9786bc5 100644
--- a/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp
+++ b/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp
@@ -95,6 +95,16 @@ bool AudioRendererPrivate::Drain() const
return audioRenderer->DrainAudioStream();
}
+bool AudioRendererPrivate::Flush() const
+{
+ return audioRenderer->FlushAudioStream();
+}
+
+bool AudioRendererPrivate::Pause() const
+{
+ return audioRenderer->PauseAudioStream();
+}
+
bool AudioRendererPrivate::Stop() const
{
return audioRenderer->StopAudioStream();
diff --git a/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h b/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h
index ce6d9e8de627417ec6570f2844f348b5a322d501..649f795212d17e2412d98ebb5bd5bd862e0fc110 100644
--- a/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h
+++ b/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h
@@ -53,7 +53,9 @@ enum RendererState {
/** Renderer Released state */
RENDERER_RELEASED,
/** INVALID state */
- RENDERER_INVALID
+ RENDERER_INVALID,
+ /** Renderer Paused state */
+ RENDERER_PAUSED
};
/**
@@ -154,6 +156,20 @@ public:
*/
virtual bool Drain() const = 0;
+ /**
+ * @brief flush renderer stream.
+ *
+ * @return Returns true if the object is successfully flushed; returns false otherwise.
+ */
+ virtual bool Flush() const = 0;
+
+ /**
+ * @brief Pauses audio rendering.
+ *
+ * @return Returns true if the rendering is successfully Paused; returns false otherwise.
+ */
+ virtual bool Pause() const = 0;
+
/**
* @brief Stops audio rendering.
*
diff --git a/interfaces/innerkits/native/audiostream/include/audio_stream.h b/interfaces/innerkits/native/audiostream/include/audio_stream.h
index d24838e832adab38adf42e23fb3446321b8b7af8..66694d6f6ea7cda09d9f350f30f6da529583c996 100644
--- a/interfaces/innerkits/native/audiostream/include/audio_stream.h
+++ b/interfaces/innerkits/native/audiostream/include/audio_stream.h
@@ -43,7 +43,9 @@ enum State {
/** Released */
RELEASED,
/** INVALID */
- INVALID
+ INVALID,
+ /** Paused */
+ PAUSED
};
class AudioStream : public AudioSession {
@@ -68,6 +70,7 @@ public:
// Common APIs
bool StartAudioStream();
+ bool PauseAudioStream();
bool StopAudioStream();
bool ReleaseAudioStream();
bool FlushAudioStream();
diff --git a/services/include/client/audio_service_client.h b/services/include/client/audio_service_client.h
index d8b39f746380943c3b046b98f3c8e8e15a9639c5..a9374d1df27e6b0c15e1a584a165f72e1d7297f6 100644
--- a/services/include/client/audio_service_client.h
+++ b/services/include/client/audio_service_client.h
@@ -132,12 +132,11 @@ public:
int32_t DrainStream();
/**
- * Pauses the stream using the session ID
+ * Pauses the stream
*
- * @param sessionID indicates the ID for the active stream to be controlled
* @return Returns {@code 0} if success; returns {@code -1} otherwise.
*/
- int32_t PauseStream(uint32_t sessionID);
+ int32_t PauseStream();
/**
* Sets the volume of the stream associated with session ID
diff --git a/services/src/client/audio_service_client.cpp b/services/src/client/audio_service_client.cpp
index cc63a15612c42369325581998fc493e47a0b9f21..a14230a1281962d5d4522315cc763a5b21b09fe5 100644
--- a/services/src/client/audio_service_client.cpp
+++ b/services/src/client/audio_service_client.cpp
@@ -560,10 +560,9 @@ int32_t AudioServiceClient::StartStream()
}
}
-int32_t AudioServiceClient::PauseStream(uint32_t sessionID)
+int32_t AudioServiceClient::PauseStream()
{
- CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
- return AUDIO_CLIENT_SUCCESS;
+ return StopStream();
}
int32_t AudioServiceClient::StopStream()
@@ -628,6 +627,9 @@ int32_t AudioServiceClient::FlushStream()
return AUDIO_CLIENT_ERR;
} else {
MEDIA_INFO_LOG("Stream Flushed Successfully");
+ acache.readIndex = 0;
+ acache.writeIndex = 0;
+ acache.isFull = false;
return AUDIO_CLIENT_SUCCESS;
}
}
diff --git a/services/src/client/audio_stream.cpp b/services/src/client/audio_stream.cpp
index 22f6c473b3f662396f2197f811bad7b7fd04dc1e..7eb856689e3c105688f581b432e44e240b757227 100644
--- a/services/src/client/audio_stream.cpp
+++ b/services/src/client/audio_stream.cpp
@@ -207,7 +207,7 @@ int32_t AudioStream::SetAudioStreamInfo(const AudioStreamParams info)
bool AudioStream::StartAudioStream()
{
- if ((state_ != PREPARED) && (state_ != STOPPED)) {
+ if ((state_ != PREPARED) && (state_ != STOPPED) && (state_ != PAUSED)) {
MEDIA_ERR_LOG("StartAudioStream Illegal state:%{public}u", state_);
return false;
}
@@ -279,6 +279,28 @@ size_t AudioStream::Write(uint8_t *buffer, size_t buffer_size)
return bytesWritten;
}
+bool AudioStream::PauseAudioStream()
+{
+ if (state_ != RUNNING) {
+ MEDIA_ERR_LOG("PauseAudioStream: State is not RUNNING. Illegal state:%{public}u", state_);
+ return false;
+ }
+ State oldState = state_;
+ state_ = PAUSED; // Set it before stopping as Read/Write and Stop can be called from different threads
+ while (isReadInProgress_ || isWriteInProgress_) {
+ }
+
+ int32_t ret = PauseStream();
+ if (ret != SUCCESS) {
+ MEDIA_DEBUG_LOG("StreamPause fail,ret:0x%{public}x", ret);
+ state_ = oldState;
+ return false;
+ }
+ MEDIA_INFO_LOG("PauseAudioStream SUCCESS");
+
+ return true;
+}
+
bool AudioStream::StopAudioStream()
{
if (state_ != RUNNING) {
@@ -303,7 +325,7 @@ bool AudioStream::StopAudioStream()
bool AudioStream::FlushAudioStream()
{
- if (state_ != RUNNING) {
+ if ((state_ != RUNNING) && (state_ != PAUSED)) {
MEDIA_ERR_LOG("FlushAudioStream: State is not RUNNING. Illegal state:%{public}u", state_);
return false;
}
diff --git a/services/test/audio_renderer_test.cpp b/services/test/audio_renderer_test.cpp
index 7e8418e7703a57899b17912c2d5f19d96cdd8967..9deecb7c9cb7cd36371bcfe92902b0ec073e23d4 100644
--- a/services/test/audio_renderer_test.cpp
+++ b/services/test/audio_renderer_test.cpp
@@ -26,6 +26,10 @@ namespace AudioTestConstants {
constexpr int32_t ARGS_INDEX_TWO = 2;
constexpr int32_t ARGS_COUNT_TWO = 2;
constexpr int32_t SUCCESS = 0;
+ constexpr int32_t STOP_BUFFER_POSITION = 700000;
+ constexpr int32_t PAUSE_BUFFER_POSITION = 1400000;
+ constexpr int32_t PAUSE_RENDER_TIME_SECONDS = 1;
+ constexpr int32_t STOP_RENDER_TIME_SECONDS = 1;
}
class AudioRendererTest {
@@ -115,12 +119,41 @@ public:
size_t bytesWritten = 0;
size_t minBytes = 4;
uint64_t latency;
+ bool stopTested = false;
+ bool pauseTested = false;
while (!feof(wavFile)) {
bytesToWrite = fread(buffer, 1, bufferLen, wavFile);
bytesWritten = 0;
MEDIA_INFO_LOG("AudioRendererTest: Bytes to write: %{public}d", bytesToWrite);
+ uint64_t currFilePos = ftell(wavFile);
+ MEDIA_INFO_LOG("AudioRendererTest: Current file position: %{public}llu", currFilePos);
+ if (!stopTested && (currFilePos > AudioTestConstants::STOP_BUFFER_POSITION) && audioRenderer->Stop()) {
+ MEDIA_INFO_LOG("Audio render stopping for 1 second");
+ stopTested = true;
+ sleep(AudioTestConstants::STOP_RENDER_TIME_SECONDS);
+ MEDIA_INFO_LOG("Audio render resume");
+ if (!audioRenderer->Start()) {
+ MEDIA_ERR_LOG("resume stream failed");
+ break;
+ }
+ } else if (!pauseTested && (currFilePos > AudioTestConstants::PAUSE_BUFFER_POSITION)
+ && audioRenderer->Pause()) {
+ MEDIA_INFO_LOG("Audio render pausing for 1 second");
+ pauseTested = true;
+ sleep(AudioTestConstants::PAUSE_RENDER_TIME_SECONDS);
+ MEDIA_INFO_LOG("Audio render resume");
+ if (!audioRenderer->Flush()) {
+ MEDIA_ERR_LOG("AudioRendererTest: flush failed");
+ break;
+ }
+ if (!audioRenderer->Start()) {
+ MEDIA_ERR_LOG("resume stream failed");
+ break;
+ }
+ }
+
if (audioRenderer->GetLatency(latency)) {
MEDIA_ERR_LOG("AudioRendererTest: GetLatency failed");
break;
@@ -183,7 +216,7 @@ public:
return false;
}
- if (StartRender(audioRenderer, wavFile)) {
+ if (!StartRender(audioRenderer, wavFile)) {
MEDIA_ERR_LOG("AudioRendererTest: Start render failed");
return false;
}