diff --git a/services/audio_service/client/src/audio_process_in_client.cpp b/services/audio_service/client/src/audio_process_in_client.cpp index 4cafb29457f9a3f815c5cc71a88129055bc486e5..b21e23d6ca23513e643a45e9b26211c1cb36ffd8 100644 --- a/services/audio_service/client/src/audio_process_in_client.cpp +++ b/services/audio_service/client/src/audio_process_in_client.cpp @@ -146,6 +146,8 @@ private: bool KeepLoopRunning(); bool KeepLoopRunningIndependent(); + void CallExitStandBy(); + void ProcessCallbackFuc(); void ProcessCallbackFucIndependent(); void RecordProcessCallbackFuc(); @@ -1231,6 +1233,16 @@ bool AudioProcessInClientInner::ClientPrepareNextLoop(uint64_t curWritePos, int6 return true; } +void AudioProcessInClientInner::CallExitStandBy() +{ + Trace trace("AudioProcessInClient::CallExitStandBy::" + std::to_string(sessionId_)); + int32_t result = processProxy_->Start(); + StreamStatus targetStatus = StreamStatus::STREAM_STARTING; + bool ret = streamStatus_->compare_exchange_strong(targetStatus, StreamStatus::STREAM_RUNNING); + AUDIO_INFO_LOG("Call start result:%{public}d status change: %{public}s", result, ret ? "success" : "fail"); + UpdateHandleInfo(); +} + std::string AudioProcessInClientInner::GetStatusInfo(StreamStatus status) { switch (status) { @@ -1265,6 +1277,10 @@ bool AudioProcessInClientInner::KeepLoopRunning() switch (streamStatus_->load()) { case STREAM_RUNNING: return true; + case STREAM_STAND_BY: + AUDIO_INFO_LOG("Status is STAND_BY, let's call exit!"); + CallExitStandBy(); + return true; case STREAM_STARTING: targetStatus = STREAM_RUNNING; break; diff --git a/services/audio_service/common/include/oh_audio_buffer.h b/services/audio_service/common/include/oh_audio_buffer.h index 2541d520c09fdf3735dae9200c6586b18f221131..ddc5eaa97bf5e34ea7d09c9a5147a7bfdca8d174 100644 --- a/services/audio_service/common/include/oh_audio_buffer.h +++ b/services/audio_service/common/include/oh_audio_buffer.h @@ -166,6 +166,9 @@ public: uint32_t GetSpanCount(); + int64_t GetLastWrittenTime(); + void SetLastWrittenTime(int64_t time); + std::atomic *GetFutex(); uint8_t *GetDataBase(); size_t GetDataSize(); @@ -178,6 +181,9 @@ private: uint32_t spanSizeInFrame_; uint32_t byteSizePerFrame_; + // available only in single process + int64_t lastWrittenTime_ = 0; + // calculated in advance size_t totalSizeInByte_ = 0; size_t spanSizeInByte_ = 0; diff --git a/services/audio_service/common/src/oh_audio_buffer.cpp b/services/audio_service/common/src/oh_audio_buffer.cpp index 7855ad72a9c44e3ec0ef1291684403bb3b9bb827..d8fec9020e0f77479ca461de6651b8ca97de7627 100644 --- a/services/audio_service/common/src/oh_audio_buffer.cpp +++ b/services/audio_service/common/src/oh_audio_buffer.cpp @@ -667,6 +667,16 @@ uint32_t OHAudioBuffer::GetSpanCount() return spanConut_; } +int64_t OHAudioBuffer::GetLastWrittenTime() +{ + return lastWrittenTime_; +} + +void OHAudioBuffer::SetLastWrittenTime(int64_t time) +{ + lastWrittenTime_ = time; +} + std::atomic *OHAudioBuffer::GetFutex() { return &basicBufferInfo_->futexObj; diff --git a/services/audio_service/server/src/audio_endpoint.cpp b/services/audio_service/server/src/audio_endpoint.cpp index 4a2b3c18d85f468b401875d0e66227555ed9ca5f..cf0a8f233b38b37ba0a0d1e7e6f0e921deb870c9 100644 --- a/services/audio_service/server/src/audio_endpoint.cpp +++ b/services/audio_service/server/src/audio_endpoint.cpp @@ -54,6 +54,7 @@ namespace { static constexpr int64_t RECORD_VOIP_DELAY_TIME = 10000000; // 10ms static constexpr int64_t MAX_SPAN_DURATION_IN_NANO = 100000000; // 100ms static constexpr int64_t DELAY_STOP_HDI_TIME = 10000000000; // 10s + static constexpr int64_t WAIT_CLIENT_STANDBY_TIME_NS = 1000000000; // 1s static constexpr int64_t DELAY_STOP_HDI_TIME_FOR_ZERO_VOLUME = 4000000000; // 4s static constexpr int32_t SLEEP_TIME_IN_DEFAULT = 400; // 400ms static constexpr int64_t DELTA_TO_REAL_READ_START_TIME = 0; // 0ms @@ -197,6 +198,7 @@ private: int32_t GetProcLastWriteDoneInfo(const std::shared_ptr processBuffer, uint64_t curWriteFrame, uint64_t &proHandleFrame, int64_t &proHandleTime); + void CheckStandBy(); bool IsAnyProcessRunning(); bool CheckAllBufferReady(int64_t checkTime, uint64_t curWritePos); bool ProcessToEndpointDataHandle(uint64_t curWritePos); @@ -1248,9 +1250,28 @@ int32_t AudioEndpointInner::UnlinkProcessStream(IAudioProcessStream *processStre return SUCCESS; } +void AudioEndpointInner::CheckStandBy() +{ + if (endpointStatus_ == RUNNING) { + endpointStatus_ = IsAnyProcessRunning() ? RUNNING : IDEL; + } + + if (endpointStatus_ == RUNNING) { + return; + } + + AUDIO_INFO_LOG("endpoint status:%{public}s", GetStatusStr(endpointStatus_).c_str()); + if (endpointStatus_ == IDEL) { + // delay call sink stop when no process running + AUDIO_INFO_LOG("status is IDEL, need delay call stop"); + delayStopTime_ = ClockTime::GetCurNano() + DELAY_STOP_HDI_TIME; + } +} + bool AudioEndpointInner::CheckAllBufferReady(int64_t checkTime, uint64_t curWritePos) { bool isAllReady = true; + bool needCheckStandby = false; { // lock list without sleep std::lock_guard lock(listLock_); @@ -1266,16 +1287,32 @@ bool AudioEndpointInner::CheckAllBufferReady(int64_t checkTime, uint64_t curWrit processBufferList_[i]->SetHandleInfo(eachCurReadPos, lastHandleProcessTime_ + duration); continue; // process not running } + // Status is RUNNING + int64_t current = ClockTime::GetCurNano(); + int64_t lastWrittenTime = tempBuffer->GetLastWrittenTime(); + if (current - lastWrittenTime > WAIT_CLIENT_STANDBY_TIME_NS) { + Trace trace("AudioEndpoint::MarkClientStandby"); + AUDIO_INFO_LOG("Find one process did not write data for more than 1s, change the status to stand-by"); + tempBuffer->GetStreamStatus()->store(StreamStatus::STREAM_STAND_BY); + needCheckStandby = true; + continue; + } uint64_t curRead = tempBuffer->GetCurReadFrame(); SpanInfo *curReadSpan = tempBuffer->GetSpanInfo(curRead); if (curReadSpan == nullptr || curReadSpan->spanStatus != SpanStatus::SPAN_WRITE_DONE) { AUDIO_DEBUG_LOG("Find one process not ready"); // print uid of the process? isAllReady = false; - break; + continue; } + // process Status is RUNNING && buffer status is WRITE_DONE + tempBuffer->SetLastWrittenTime(current); } } + if (needCheckStandby) { + CheckStandBy(); + } + if (!isAllReady) { Trace trace("AudioEndpoint::WaitAllProcessReady"); int64_t tempWakeupTime = readTimeModel_.GetTimeOfPos(curWritePos) + WRITE_TO_HDI_AHEAD_TIME; diff --git a/services/audio_service/server/src/audio_process_in_server.cpp b/services/audio_service/server/src/audio_process_in_server.cpp index f4b593f3adbadd953e9e44e337422c469e3b64e4..0637ae7a7d252a589207954363a2a59ad285b977 100644 --- a/services/audio_service/server/src/audio_process_in_server.cpp +++ b/services/audio_service/server/src/audio_process_in_server.cpp @@ -91,7 +91,7 @@ int32_t AudioProcessInServer::Start() CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!"); std::lock_guard lock(statusLock_); - CHECK_AND_RETURN_RET_LOG(streamStatus_->load() == STREAM_STARTING, + CHECK_AND_RETURN_RET_LOG(streamStatus_->load() == STREAM_STARTING || streamStatus_->load() == STREAM_STAND_BY, ERR_ILLEGAL_STATE, "Start failed, invalid status."); if (processConfig_.audioMode != AUDIO_MODE_PLAYBACK && !needCheckBackground_ && @@ -110,6 +110,12 @@ int32_t AudioProcessInServer::Start() listenerList_[i]->OnStart(this); } + if (streamStatus_->load() == STREAM_STAND_BY) { + AUDIO_INFO_LOG("Call start while in stand-by"); + streamStatus_->store(STREAM_STARTING); + } + processBuffer_->SetLastWrittenTime(ClockTime::GetCurNano()); + AUDIO_INFO_LOG("Start in server success!"); return SUCCESS; } @@ -323,6 +329,7 @@ int32_t AudioProcessInServer::InitBufferStatus() spanInfo->volumeEnd = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize spanInfo->isMute = false; } + processBuffer_->SetLastWrittenTime(ClockTime::GetCurNano()); return SUCCESS; }